2 ** LCLint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2000 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 "aliasChecks.h"
36 # include "exprNodeSList.h"
37 # include "exprData.i"
39 static bool exprNode_isEmptyStatement (exprNode p_e);
40 static /*@exposed@*/ exprNode exprNode_firstStatement (/*@returned@*/ exprNode p_e);
41 static bool exprNode_isFalseConstant (exprNode p_e) /*@*/ ;
42 static bool exprNode_isBlock (exprNode p_e);
43 static void checkGlobUse (uentry p_glob, bool p_isCall, /*@notnull@*/ exprNode p_e);
44 static void exprNode_addUse (exprNode p_e, sRef p_s);
45 static bool exprNode_matchArgType (ctype p_ct, exprNode p_e);
47 static exprNode exprNode_statementError (/*@only@*/ exprNode p_e, /*@only@*/ lltok p_t);
48 static bool exprNode_matchTypes (exprNode p_e1, exprNode p_e2);
49 static void checkUniqueParams (exprNode p_fcn,
50 /*@notnull@*/ exprNode p_current, exprNodeList p_args,
51 int p_paramno, uentry p_ucurrent);
52 static void updateAliases (/*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2);
53 static void abstractOpError (ctype p_tr1, ctype p_tr2, lltok p_op,
54 /*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2,
55 fileloc p_loc1, fileloc p_loc2);
56 static ctype checkNumerics (ctype p_tr1, ctype p_tr2, ctype p_te1, ctype p_te2,
57 /*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2, lltok p_op);
58 static void doAssign (/*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2, bool p_isInit);
59 static void checkSafeUse (exprNode p_e, sRef p_s);
60 static void reflectNullTest (/*@notnull@*/ exprNode p_e, bool p_isnull);
61 static void checkMacroParen (exprNode p_e);
62 static exprNodeSList exprNode_flatten (/*@dependent@*/ exprNode p_e);
63 static void exprNode_checkSetAny (exprNode p_e, /*@dependent@*/ cstring p_name);
64 static void exprNode_checkUse (exprNode p_e, sRef p_s, fileloc p_loc);
65 static void exprNode_mergeUSs (exprNode p_res, exprNode p_other);
66 static void exprNode_mergeCondUSs (exprNode p_res, exprNode p_other1, exprNode p_other2);
67 static /*@only@*/ /*@notnull@*/ exprNode exprNode_fromIdentifierAux (/*@observer@*/ uentry p_c);
68 static void checkAnyCall (/*@notnull@*/ /*@dependent@*/ exprNode p_fcn,
69 /*@dependent@*/ cstring p_fname,
70 uentryList p_pn, exprNodeList p_args,
71 bool p_hasMods, sRefSet p_mods, bool p_isSpec,
73 static void checkOneArg (uentry p_ucurrent, /*@notnull@*/ exprNode p_current,
74 /*@dependent@*/ exprNode p_fcn, bool p_isSpec, int p_argno, int p_totargs);
76 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode p_fcn, uentryList p_params, exprNodeList p_args);
78 static /*@only@*/ exprNode exprNode_effect (exprNode p_e)
79 /*@globals internalState@*/ ;
80 static /*@only@*/ cstring exprNode_doUnparse (exprNode p_e);
81 static /*@observer@*/ cstring exprNode_rootVarName (exprNode p_e);
82 static /*@exposed@*/ exprNode
83 exprNode_lastStatement (/*@returned@*/ exprNode p_e);
85 static /*@null@*/ sRef defref = sRef_undefined;
86 static /*@only@*/ exprNode mustExitNode = exprNode_undefined;
88 static int checkArgsReal (uentry p_fcn, /*@dependent@*/ exprNode p_f,
90 exprNodeList p_args, bool p_isIter, exprNode p_ret);
92 static bool inEffect = FALSE;
93 static int nowalloc = 0;
94 static int totalloc = 0;
95 static int maxalloc = 0;
97 static /*@only@*/ uentry regArg;
98 static /*@only@*/ uentry outArg;
99 static /*@only@*/ uentry outStringArg;
100 static /*@exposed@*/ sRef stdinRef;
101 static /*@exposed@*/ sRef stdoutRef;
102 static /*@only@*/ uentry csArg;
103 static /*@only@*/ uentry csOnlyArg;
104 static ctype cstringType;
105 static ctype ctypeType;
106 static ctype filelocType;
107 static bool initMod = FALSE;
109 # define exprNode_defineConstraints(e) { \
110 (e)->requiresConstraints = constraintList_makeNew(); \
111 (e)->ensuresConstraints = constraintList_makeNew(); \
112 (e)->trueEnsuresConstraints = constraintList_makeNew(); \
113 (e)->falseEnsuresConstraints = constraintList_makeNew(); }
116 ** must occur after library has been read
119 void exprNode_initMod (void)
120 /*@globals undef regArg, undef outArg, undef outStringArg,
121 undef csOnlyArg, undef csArg;
128 cstringType = ctype_unknown;
129 ctypeType = ctype_unknown;
130 filelocType = ctype_unknown;
132 defref = sRef_undefined;
134 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
136 cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
139 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
141 ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
144 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
146 filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
149 if (usymtab_existsGlob (cstring_makeLiteralTemp ("stdin")))
151 ue = usymtab_lookupGlob (cstring_makeLiteralTemp ("stdin"));
153 else /* define stdin */
155 ue = uentry_makeVariable (cstring_makeLiteralTemp ("stdin"),
157 fileloc_getBuiltin (),
159 uentry_setHasNameError (ue);
160 ue = usymtab_supGlobalEntryReturn (ue);
163 stdinRef = sRef_makePointer (uentry_getSref (ue));
165 if (usymtab_existsGlob (cstring_makeLiteralTemp ("stdout")))
167 ue = usymtab_lookupGlob (cstring_makeLiteralTemp ("stdout"));
171 ue = uentry_makeVariable (cstring_makeLiteralTemp ("stdout"),
173 fileloc_getBuiltin (),
175 uentry_setHasNameError (ue);
176 ue = usymtab_supGlobalEntryReturn (ue);
179 stdoutRef = sRef_makePointer (uentry_getSref (ue));
181 tmp = idDecl_create (cstring_undefined, qtype_create (ctype_unknown));
183 regArg = uentry_makeParam (tmp, PARAMUNKNOWN);
186 qtype_addQual (qtype_create (ctype_makePointer (ctype_unknown)),
189 outArg = uentry_makeParam (tmp, PARAMUNKNOWN);
191 idDecl_setTyp (tmp, qtype_addQual (qtype_create (ctype_string),
194 outStringArg = uentry_makeParam (tmp, PARAMUNKNOWN);
196 idDecl_setTyp (tmp, qtype_addQual (qtype_addQual (qtype_create (cstringType),
198 qual_createNull ()));
200 csOnlyArg = uentry_makeParam (tmp, PARAMUNKNOWN);
202 idDecl_setTyp (tmp, qtype_addQual (qtype_create (cstringType), qual_createNull ()));
203 csArg = uentry_makeParam (tmp, PARAMUNKNOWN);
209 exprNode_destroyMod (void)
210 /*@globals killed regArg, killed outArg, killed outStringArg,
211 killed mustExitNode, initMod @*/
215 uentry_free (regArg);
216 uentry_free (outArg);
217 uentry_free (outStringArg);
219 exprNode_free (mustExitNode);
226 static void exprNode_resetSref (/*@notnull@*/ exprNode e)
231 static bool isFlagKey (char key)
233 return (key == '-' || key == '+' || key == ' ' || key == '#');
236 static void exprNode_combineControl (/*@notnull@*/ exprNode ret,
237 /*@notnull@*/ exprNode ifclause,
238 /*@notnull@*/ exprNode elseclause)
240 ret->canBreak = ifclause->canBreak || elseclause->canBreak;
243 (ifclause->mustBreak || exprNode_mustEscape (ifclause))
244 && (elseclause->mustBreak || exprNode_mustEscape (elseclause));
246 ret->exitCode = exitkind_combine (ifclause->exitCode,
247 elseclause->exitCode);
252 ** For exprNode's returned by exprNode_effect.
255 static bool shallowKind (exprKind kind)
257 return (kind == XPR_STRINGLITERAL
258 || kind == XPR_NUMLIT
261 || kind == XPR_NODE);
265 exprNode_freeIniter (/*@only@*/ exprNode e)
267 if (!exprNode_isError (e))
272 sfree (e->edata->field);
276 exprNode_free (e->edata->op->b);
277 /*@-compdestroy@*/ sfree (e->edata->op); /*@=compdestroy@*/
281 llbug (message ("other: %s", exprNode_unparse (e)));
284 multiVal_free (e->val);
285 cstring_free (e->etext);
286 fileloc_free (e->loc);
287 sRefSet_free (e->uses);
288 sRefSet_free (e->sets);
289 sRefSet_free (e->msets);
290 guardSet_free (e->guards);
296 exprNode_freeShallow (/*@only@*/ exprNode e)
298 if (!exprNode_isError (e))
300 if (shallowKind (e->kind))
307 if (e->kind == XPR_EMPTY
308 || e->kind == XPR_BODY
309 || e->kind == XPR_STRINGLITERAL
310 || e->kind == XPR_NUMLIT
311 || e->kind == XPR_NODE
312 || e->kind == XPR_OFFSETOF
313 || e->kind == XPR_ALIGNOFT
314 || e->kind == XPR_ALIGNOF
315 || e->kind == XPR_SIZEOFT
316 || e->kind == XPR_SIZEOF)
318 /* don't free anything */
322 /* multiVal_free (e->val); */
323 cstring_free (e->etext);
324 fileloc_free (e->loc);
325 sRefSet_free (e->uses);
326 sRefSet_free (e->sets);
327 sRefSet_free (e->msets);
328 guardSet_free (e->guards);
329 exprData_freeShallow (e->edata, e->kind);
331 /*@-compdestroy@*/ sfree (e); /*@=compdestroy@*/
340 exprNode_free (exprNode e)
342 if (!exprNode_isError (e))
346 multiVal_free (e->val);
347 cstring_free (e->etext);
348 fileloc_free (e->loc);
349 sRefSet_free (e->uses);
350 sRefSet_free (e->sets);
351 sRefSet_free (e->msets);
352 guardSet_free (e->guards);
353 exprData_free (e->edata, e->kind);
363 exprNode_makeError ()
365 return exprNode_undefined;
368 static /*@out@*/ /*@only@*/ /*@notnull@*/ exprNode
371 exprNode ret = (exprNode) dmalloc (sizeof (*ret));
372 /* static int lastexpnodes = 0; */
377 if (nowalloc > maxalloc)
385 static /*@notnull@*/ /*@special@*/ exprNode
386 exprNode_createPlain (ctype c)
388 /*@post:isnull result->edata, result->loc, result->val, result->guards,
389 result->uses, result->sets, result->msets, result->etext @*/
392 exprNode e = exprNode_new ();
396 e->val = multiVal_undefined;
398 e->etext = cstring_undefined;
399 e->loc = fileloc_undefined;
400 e->guards = guardSet_undefined;
401 e->uses = sRefSet_undefined;
402 e->sets = sRefSet_undefined;
403 e->msets = sRefSet_undefined;
404 e->edata = exprData_undefined;
405 e->exitCode = XK_NEVERESCAPE;
407 e->mustBreak = FALSE;
408 e->isJumpPoint = FALSE;
410 exprNode_defineConstraints(e);
415 /*@observer@*/ exprNode exprNode_makeMustExit (void)
417 if (exprNode_isUndefined (mustExitNode))
419 mustExitNode = exprNode_createPlain (ctype_unknown);
420 mustExitNode->exitCode = XK_MUSTEXIT;
427 static /*@notnull@*/ /*@special@*/ exprNode exprNode_create (ctype c)
429 /*@post:isnull result->edata, result->guards, result->val,
430 result->uses, result->sets, result->msets@*/
433 exprNode e = exprNode_createPlain (c);
434 e->loc = fileloc_copy (g_currentloc);
438 static /*@notnull@*/ /*@special@*/ exprNode exprNode_createUnknown (void)
440 /*@post:isnull result->edata, result->guards,
441 result->uses, result->sets, result->msets@*/
444 return (exprNode_create (ctype_unknown));
447 static /*@notnull@*/ /*@special@*/ exprNode
448 exprNode_createLoc (ctype c, /*@keep@*/ fileloc loc)
450 /*@post:isnull result->edata, result->guards, result->val,
451 result->uses, result->sets, result->msets@*/
454 exprNode e = exprNode_createPlain (c);
460 exprNode_copySets (/*@special@*/ /*@notnull@*/ exprNode ret, exprNode e)
461 /*@defines ret->guards, ret->uses, ret->sets, ret->msets@*/
463 if (exprNode_isDefined (e))
465 ret->guards = guardSet_copy (e->guards);
466 ret->uses = sRefSet_newCopy (e->uses);
467 ret->sets = sRefSet_newCopy (e->sets);
468 ret->msets = sRefSet_newCopy (e->msets);
472 ret->guards = guardSet_undefined;
473 ret->uses = sRefSet_undefined;
474 ret->sets = sRefSet_undefined;
475 ret->msets = sRefSet_undefined;
479 static /*@notnull@*/ /*@special@*/ exprNode
480 exprNode_createPartialLocCopy (exprNode e, /*@only@*/ fileloc loc)
482 /*@post:isnull result->edata, result->etext@*/
485 exprNode ret = exprNode_new ();
487 if (exprNode_isError (e))
489 ret->typ = ctype_unknown;
490 ret->val = multiVal_undefined;
492 ret->guards = guardSet_undefined;
493 ret->uses = sRefSet_undefined;
494 ret->sets = sRefSet_undefined;
495 ret->msets = sRefSet_undefined;
500 ret->val = multiVal_copy (e->val);
502 ret->guards = guardSet_copy (e->guards);
503 ret->uses = sRefSet_newCopy (e->uses);
504 ret->sets = sRefSet_newCopy (e->sets);
505 ret->msets = sRefSet_newCopy (e->msets);
508 ret->kind = XPR_EMPTY;
510 ret->etext = cstring_undefined;
511 ret->exitCode = XK_NEVERESCAPE;
512 ret->canBreak = FALSE;
513 ret->mustBreak = FALSE;
514 ret->isJumpPoint = FALSE;
515 ret->edata = exprData_undefined;
521 static /*@notnull@*/ /*@special@*/ exprNode
522 exprNode_createPartialCopy (exprNode e)
524 /*@post:isnull result->edata, result->etext@*/
527 return (exprNode_createPartialLocCopy (e, fileloc_copy (exprNode_loc (e))));
530 static /*@notnull@*/ /*@special@*/ exprNode
531 exprNode_createPartialNVCopy (exprNode e)
533 /*@post:isnull result->edata, result->etext, result->val @*/
536 exprNode ret = exprNode_new ();
538 if (exprNode_isError (e))
540 ret->typ = ctype_unknown;
541 ret->loc = fileloc_undefined;
542 ret->guards = guardSet_undefined;
543 ret->uses = sRefSet_undefined;
544 ret->sets = sRefSet_undefined;
545 ret->msets = sRefSet_undefined;
550 ret->loc = fileloc_copy (e->loc);
551 ret->guards = guardSet_copy (e->guards);
552 ret->uses = sRefSet_newCopy (e->uses);
553 ret->sets = sRefSet_newCopy (e->sets);
554 ret->msets = sRefSet_newCopy (e->msets);
557 ret->val = multiVal_undefined;
558 ret->kind = XPR_EMPTY;
560 ret->etext = cstring_undefined;
561 ret->exitCode = XK_NEVERESCAPE;
562 ret->canBreak = FALSE;
563 ret->mustBreak = FALSE;
564 ret->isJumpPoint = FALSE;
565 ret->edata = exprData_undefined;
570 static /*@notnull@*/ /*@special@*/ exprNode
571 exprNode_createSemiCopy (exprNode e)
573 /*@post:isnull result->edata, result->etext, result->sets,
574 result->msets, result->uses, result->guards@*/
577 if (exprNode_isError (e))
579 return exprNode_createPlain (ctype_unknown);
583 exprNode ret = exprNode_new ();
586 ret->val = multiVal_copy (e->val);
587 ret->loc = fileloc_copy (e->loc);
588 ret->guards = guardSet_undefined;
589 ret->uses = sRefSet_undefined;
590 ret->sets = sRefSet_undefined;
591 ret->msets = sRefSet_undefined;
593 ret->kind = XPR_EMPTY;
595 ret->etext = cstring_undefined;
596 ret->exitCode = XK_NEVERESCAPE;
597 ret->canBreak = FALSE;
598 ret->mustBreak = FALSE;
599 ret->isJumpPoint = FALSE;
600 ret->edata = exprData_undefined;
607 exprNode_isNullValue (exprNode e)
609 if (exprNode_isDefined (e))
611 multiVal m = exprNode_getValue (e);
613 if (multiVal_isInt (m))
615 return (multiVal_forceInt (m) == 0);
623 exprNode_isUnknownConstant (/*@notnull@*/ exprNode e)
625 while (e->kind == XPR_PARENS)
627 e = exprData_getUopNode (e->edata);
628 llassert (exprNode_isDefined (e));
631 if (e->kind == XPR_CONST)
633 multiVal m = exprNode_getValue (e);
635 if (multiVal_isUnknown (m))
645 exprNode_numLiteral (ctype c, /*@temp@*/ cstring t,
646 /*@only@*/ fileloc loc, long val)
648 exprNode e = exprNode_createLoc (c, loc);
650 e->kind = XPR_NUMLIT;
652 llassert (multiVal_isUndefined (e->val));
653 e->val = multiVal_makeInt (val);
654 e->edata = exprData_makeLiteral (cstring_copy (t));
658 e->sref = sRef_makeUnknown ();
659 sRef_setDefNull (e->sref, e->loc);
662 DPRINTF (("Num lit: %s / %s", exprNode_unparse (e), ctype_unparse (exprNode_getType (e))));
667 exprNode_charLiteral (char c, cstring text, /*@only@*/ fileloc loc)
669 exprNode e = exprNode_createLoc (ctype_char, loc);
671 if (context_getFlag (FLG_CHARINTLITERAL))
673 e->typ = ctype_makeConj (ctype_char, ctype_int);
676 e->kind = XPR_NUMLIT;
677 e->val = multiVal_makeChar (c);
679 e->edata = exprData_makeLiteral (cstring_copy (text));
684 exprNode_floatLiteral (double d, ctype ct, cstring text, /*@only@*/ fileloc loc)
686 exprNode e = exprNode_createLoc (ct, loc);
688 e->kind = XPR_NUMLIT;
689 e->val = multiVal_makeDouble (d);
690 e->edata = exprData_makeLiteral (cstring_copy (text));
694 multiVal exprNode_getValue (exprNode e)
696 while (exprNode_isInParens (e)) {
697 if (e->edata != NULL) {
698 e = exprData_getUopNode (e->edata);
704 if (exprNode_isDefined (e)) {
707 return multiVal_undefined;
712 exprNode_stringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
714 exprNode e = exprNode_createLoc (ctype_string, loc);
715 int len = cstring_length (t) - 2;
716 char *ts = cstring_toCharsSafe (t);
717 char *s = cstring_toCharsSafe (cstring_create (len + 1));
719 if (context_getFlag (FLG_STRINGLITERALLEN))
721 if (len > context_getValue (FLG_STRINGLITERALLEN))
723 voptgenerror (FLG_STRINGLITERALLEN,
725 ("String literal length (%d) exceeds maximum "
728 context_getValue (FLG_STRINGLITERALLEN),
734 strncpy (s, ts+1, size_fromInt (len));
738 e->kind = XPR_STRINGLITERAL;
739 e->val = multiVal_makeString (cstring_fromCharsO (s));
740 e->edata = exprData_makeLiteral (t);
741 e->sref = sRef_makeType (ctype_string);
742 /* Start modifications */
743 /* This expr is null terminated, so we set the len and size */
744 sRef_setNullTerminatedState(e->sref);
746 DPRINTF("Len is set to : %d\n\n", strlen((char *)multiVal_forceString(e->val)));
747 DPRINTF("Size is set to : %d\n\n", strlen((char *)multiVal_forceString(e->val)));
748 DPRINTF("State is set to: %d\n\n", e->sref->bufinfo.bufstate);
750 sRef_setLen(e->sref, (int) strlen((char *)multiVal_forceString(e->val)));
751 sRef_setSize(e->sref, (int) strlen((char *)multiVal_forceString(e->val)));
753 if (context_getFlag (FLG_READONLYSTRINGS))
755 sRef_setAliasKind (e->sref, AK_STATIC, fileloc_undefined);
756 sRef_setExKind (e->sref, XO_OBSERVER, loc);
760 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
763 return (e); /* s released */
766 exprNode exprNode_fromUIO (cstring c)
768 fileloc loc = context_getSaveLocation ();
769 exprNode e = exprNode_createPlain (ctype_unknown);
773 if (fileloc_isUndefined (loc))
775 loc = fileloc_copy (g_currentloc);
778 e->loc = loc; /* save loc was mangled */
781 if (usymtab_exists (c))
783 uentry ue = usymtab_lookupEither (c);
785 if (uentry_isDatatype (ue)
786 && uentry_isSpecified (ue))
789 (message ("%q: Specified datatype %s used in code, but not defined. "
790 "(Cannot continue reasonably from this error.)",
791 fileloc_unparse (e->loc), c));
799 llassertprint (!usymtab_exists (c), ("Entry exists: %s", c));
802 ** was supercedeGlobalEntry...is this better?
805 if (!context_inIterEnd ())
807 if (context_inMacro ())
809 if (context_getFlag (FLG_UNRECOG))
813 message ("Unrecognized identifier in macro definition: %s", c), e->loc);
817 flagcode_recordSuppressed (FLG_UNRECOG);
823 (FLG_UNRECOG, message ("Unrecognized identifier: %s", c),
828 e->edata = exprData_makeId (uentry_makeUnrecognized (c, fileloc_copy (loc)));
830 /* No alias errors for unrecognized identifiers */
831 sRef_setAliasKind (e->sref, AK_ERROR, loc);
836 exprNode exprNode_createId (/*@observer@*/ uentry c)
838 if (uentry_isValid (c))
840 exprNode e = exprNode_new ();
842 e->typ = uentry_getType (c);
844 if (uentry_isFunction (c)
845 && !sRef_isLocalVar (uentry_getSref (c)))
847 e->sref = sRef_undefined;
851 e->sref = uentry_getSref (c);
854 if (sRef_isStateUnknown (e->sref) && uentry_isNonLocal (c))
856 sRef_setDefined (e->sref, fileloc_undefined);
860 ** yoikes! leaving this out was a heinous bug...that would have been
861 ** caught if i had lclint working first. gag!
864 e->etext = cstring_undefined;
866 if (uentry_isEitherConstant (c))
869 e->val = multiVal_copy (uentry_getConstantValue (c));
874 e->val = multiVal_unknown ();
877 e->edata = exprData_makeId (c);
878 e->loc = context_getSaveLocation ();
880 if (fileloc_isUndefined (e->loc))
882 fileloc_free (e->loc);
883 e->loc = fileloc_copy (g_currentloc);
886 e->guards = guardSet_new ();
887 e->sets = sRefSet_new ();
888 e->msets = sRefSet_new ();
889 e->uses = sRefSet_new ();
891 /*> missing fields, detected by lclint <*/
892 e->exitCode = XK_NEVERESCAPE;
893 e->isJumpPoint = FALSE;
895 e->mustBreak = FALSE;
897 exprNode_defineConstraints(e);
903 return exprNode_createUnknown ();
907 /*@notnull@*/ exprNode
908 exprNode_fromIdentifier (/*@observer@*/ uentry c)
912 if (context_justPopped ()) /* watch out! c could be dead */
914 uentry ce = usymtab_lookupSafe (LastIdentifier ());
916 if (uentry_isValid (ce))
922 llbuglit ("Looks like Aunt Millie forgot to walk to dog again.");
926 ret = exprNode_fromIdentifierAux (c);
932 static /*@only@*/ /*@notnull@*/ exprNode
933 exprNode_fromIdentifierAux (/*@observer@*/ uentry c)
935 exprNode e = exprNode_createId (c);
938 uentry_setUsed (c, e->loc);
940 if (uentry_isVar (c) && sRef_isGlobal (sr))
942 checkGlobUse (c, FALSE, e);
949 exprNode_isZero (exprNode e)
951 if (exprNode_isDefined (e))
953 multiVal m = exprNode_getValue (e);
955 if (multiVal_isInt (m))
957 return (multiVal_forceInt (m) == 0);
965 exprNode_isNonNegative (exprNode e)
967 if (exprNode_isDefined (e))
969 multiVal m = exprNode_getValue (e);
971 if (multiVal_isInt (m))
973 return (multiVal_forceInt (m) >= 0);
981 ** a[x] - uses a but NOT a[]
982 ** result sref = a[] (set/use in assignment)
984 ** The syntax x[a] is also legal in C, and has the same
985 ** semantics. If ind is an array, and arr is an int, flip
990 exprNode_arrayFetch (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
993 ** error in arr, error propagates (no new messages)
994 ** error in ind, assume valid and continue
997 if (exprNode_isError (e1))
1000 return (exprNode_makeError ());
1006 ctype carr = exprNode_getType (e1);
1007 ctype crarr = ctype_realType (carr);
1010 ** this sets up funny aliasing, that leads to spurious
1011 ** lclint errors. Hence, the i2 comments.
1014 if (!ctype_isRealArray (crarr)
1015 && ctype_isRealNumeric (crarr)
1016 && !exprNode_isError (e2)
1017 && ctype_isRealAP (exprNode_getType (e2))) /* fetch like 3[a] */
1022 carr = exprNode_getType (arr);
1023 crarr = ctype_realType (carr);
1031 if (sRef_possiblyNull (arr->sref))
1033 if (!usymtab_isGuarded (arr->sref))
1035 if (optgenerror (FLG_NULLDEREF,
1036 message ("Index of %s pointer %q: %s",
1037 sRef_nullMessage (arr->sref),
1038 sRef_unparse (arr->sref),
1039 exprNode_unparse (arr)),
1042 sRef_showNullInfo (arr->sref);
1044 /* suppress future messages */
1045 sRef_setNullError (arr->sref);
1050 if (exprNode_isError (ind))
1052 if ((ctype_isArrayPtr (crarr)
1053 && !ctype_isFunction (crarr))
1054 || ctype_isUnknown (carr))
1056 exprNode ret = exprNode_createPartialCopy (arr);
1058 if (ctype_isKnown (carr))
1060 ret->typ = ctype_baseArrayPtr (crarr);
1064 ret->typ = ctype_unknown;
1067 ret->sref = sRef_makeArrayFetch (arr->sref);
1069 ret->kind = XPR_FETCH;
1072 ** Because of funny aliasing (when arr and ind are
1073 ** flipped) spurious errors would be reported here.
1076 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1077 checkSafeUse (ret, arr->sref);
1082 voptgenerror (FLG_TYPE,
1083 message ("Array fetch from non-array (%t): %s[%s]", carr,
1084 exprNode_unparse (e1), exprNode_unparse (e2)),
1086 exprNode_free (arr);
1087 return (exprNode_makeError ());
1092 if (!ctype_isForceRealInt (&(ind->typ)))
1094 ctype rt = ctype_realType (ind->typ);
1096 if (ctype_isChar (rt))
1100 message ("Array fetch using non-integer, %t: %s[%s]",
1102 exprNode_unparse (e1), exprNode_unparse (e2)),
1105 else if (ctype_isEnum (rt))
1109 message ("Array fetch using non-integer, %t: %s[%s]",
1111 exprNode_unparse (e1), exprNode_unparse (e2)),
1118 message ("Array fetch using non-integer, %t: %s[%s]",
1120 exprNode_unparse (e1), exprNode_unparse (e2)),
1124 multiVal_free (ind->val);
1125 ind->val = multiVal_unknown ();
1128 if (ctype_isArrayPtr (crarr) && !ctype_isFunction (crarr))
1130 exprNode ret = exprNode_createSemiCopy (arr);
1131 multiVal m = exprNode_getValue (ind);
1133 ret->typ = ctype_baseArrayPtr (crarr);
1134 ret->kind = XPR_FETCH;
1136 if (multiVal_isInt (m))
1138 int i = (int) multiVal_forceInt (m);
1140 if (sRef_isValid (arr->sref)) {
1141 ret->sref = sRef_makeArrayFetchKnown (arr->sref, i);
1143 ret->sref = sRef_undefined;
1148 ret->sref = sRef_makeArrayFetch (arr->sref);
1151 ret->sets = sRefSet_realNewUnion (arr->sets, ind->sets);
1152 ret->msets = sRefSet_realNewUnion (arr->msets, ind->msets);
1153 ret->uses = sRefSet_realNewUnion (arr->uses, ind->uses);
1155 /* (see comment on spurious errors above) */
1156 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1158 exprNode_checkUse (ret, ind->sref, ind->loc);
1159 exprNode_checkUse (ret, arr->sref, arr->loc);
1165 if (ctype_isUnknown (carr))
1167 exprNode ret = exprNode_createPartialCopy (arr);
1169 ret->kind = XPR_FETCH;
1170 ret->typ = ctype_unknown;
1171 ret->sets = sRefSet_union (ret->sets, ind->sets);
1172 ret->msets = sRefSet_union (ret->msets, ind->msets);
1173 ret->uses = sRefSet_union (ret->uses, ind->uses);
1175 /* (see comment on spurious errors above) */
1176 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1178 exprNode_checkUse (ret, ind->sref, ind->loc);
1179 exprNode_checkUse (ret, arr->sref, arr->loc);
1186 message ("Array fetch from non-array (%t): %s[%s]", carr,
1187 exprNode_unparse (e1), exprNode_unparse (e2)),
1190 exprNode_free (arr);
1191 exprNode_free (ind);
1193 return (exprNode_makeError ());
1203 checkArgs (uentry fcn, /*@dependent@*/ exprNode f, ctype t,
1204 exprNodeList args, exprNode ret)
1206 return (checkArgsReal (fcn, f, ctype_argsFunction (t), args, FALSE, ret));
1210 ** checkPrintfArgs --- checks arguments for printf-like functions
1211 ** Arguments before ... have already been checked.
1212 ** The argument before the ... is a char *.
1213 ** argno is the format string argument.
1217 checkPrintfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1218 exprNodeList args, exprNode ret, int argno)
1221 ** the last argument before the elips is the format string
1226 int nargs = exprNodeList_size (args);
1227 uentryList params = uentry_getParams (fcn);
1231 ** These should be ensured by checkSpecialFunction
1234 llassert (uentryList_size (params) == argno + 1);
1235 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1237 a = exprNodeList_getN (args, argno - 1);
1238 formatloc = fileloc_copy (exprNode_loc (a));
1240 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1241 && exprNode_knownStringValue (a))
1243 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1244 char *code = format;
1247 nargs = exprNodeList_size (args);
1249 while ((code = strchr (code, '%')) != NULL)
1251 char *origcode = code;
1252 char key = *(++code);
1253 ctype modtype = ctype_int;
1254 bool modified = FALSE;
1256 fileloc_addColumn (formatloc, code - ocode);
1259 while (isFlagKey (key))
1262 fileloc_incColumn (formatloc);
1265 if (key == 'm') /* skipped in syslog */
1270 /* ignore field width */
1271 while (isdigit ((int) key) != 0)
1274 fileloc_incColumn (formatloc);
1277 /* ignore precision */
1281 fileloc_incColumn (formatloc);
1284 ** In printf, '*' means: read the next arg as an int for the
1285 ** field width. This seems to be missing from my copy of the
1286 ** standard x3.159-1989. Setion 4.9.6.1 refers to * (described
1287 ** later) but never does.
1292 ; /* don't do anything --- handle later */
1296 while (isdigit ((int) key) != 0)
1299 fileloc_incColumn (formatloc);
1306 modtype = ctype_sint; /* short */
1308 fileloc_incColumn (formatloc);
1310 else if (key == 'l' || key == 'L')
1312 modtype = ctype_lint; /* long */
1314 fileloc_incColumn (formatloc);
1316 if (key == 'l' || key == 'L') {
1317 modtype = ctype_llint; /* long long */
1319 fileloc_incColumn (formatloc);
1327 /* now, key = type of conversion to apply */
1329 fileloc_incColumn (formatloc);
1337 message ("No argument corresponding to %q format "
1338 "code %d (%%%h): \"%s\"",
1339 uentry_getName (fcn),
1341 cstring_fromChars (format)),
1344 if (fileloc_isDefined (formatloc)
1345 && context_getFlag (FLG_SHOWCOL))
1347 llgenindentmsg (cstring_makeLiteral ("Corresponding format code"),
1355 a = exprNodeList_getN (args, i);
1358 if (!exprNode_isError (a))
1364 case '*': /* int argument for fieldwidth */
1365 expecttype = ctype_int;
1366 *(--code) = '%'; /* convert it for next code */
1367 fileloc_subColumn (formatloc, 1);
1368 /*@switchbreak@*/ break;
1371 expecttype = ctype_combine (ctype_uint, modtype);
1372 /*@switchbreak@*/ break;
1374 case 'i': /* int argument */
1376 expecttype = ctype_combine (ctype_int, modtype);
1377 /*@switchbreak@*/ break;
1379 case 'x': /* unsigned int */
1381 expecttype = ctype_combine (ctype_uint, modtype);
1382 /*@switchbreak@*/ break;
1388 case 'f': /* double */
1389 expecttype = ctype_combine (ctype_double, modtype);
1390 /*@switchbreak@*/ break;
1392 case 'c': /* int converted to char (check its a char?) */
1393 expecttype = ctype_makeConj (ctype_char, ctype_uchar);
1394 /*@switchbreak@*/ break;
1396 case 's': /* string */
1397 expecttype = ctype_string;
1398 /*@switchbreak@*/ break;
1401 while (((key = *(++code)) != ']')
1404 fileloc_incColumn (formatloc);
1410 (message ("Bad character set format: %s",
1411 cstring_fromChars (origcode)));
1414 expecttype = ctype_string;
1415 /*@switchbreak@*/ break;
1417 case 'p': /* pointer */
1418 expecttype = ctype_makePointer (ctype_void);
1420 /*@switchbreak@*/ break;
1422 case 'n': /* pointer to int, modified by call! */
1423 expecttype = ctype_combine (ctype_makePointer (ctype_int), modtype);
1425 uentry_setDefState (regArg, SS_ALLOCATED); /* corresponds to out */
1426 /*@switchbreak@*/ break;
1428 case 'm': /* in a syslog, it doesn't consume an argument */
1429 /* should check we're really doing syslog */
1431 /*@switchbreak@*/ break;
1435 expecttype = ctype_unknown;
1439 message ("Unrecognized format code: %s",
1440 cstring_fromChars (origcode)),
1441 fileloc_isDefined (formatloc)
1442 ? formatloc : g_currentloc);
1444 /*@switchbreak@*/ break;
1447 if (!(exprNode_matchArgType (expecttype, a)))
1449 if (ctype_isVoidPointer (expecttype)
1450 && ctype_isRealAbstract (a->typ)
1451 && (context_getFlag (FLG_ABSTVOIDP)))
1457 if (llgenformattypeerror
1458 (expecttype, exprNode_undefined,
1460 message ("Format argument %d to %q (%%%h) expects "
1463 uentry_getName (fcn),
1465 a->typ, exprNode_unparse (a)),
1468 if (fileloc_isDefined (formatloc)
1469 && context_getFlag (FLG_SHOWCOL))
1472 (cstring_makeLiteral
1473 ("Corresponding format code"),
1480 uentry_setType (regArg, expecttype);
1481 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
1483 if (ctype_equal (expecttype, ctype_string))
1485 exprNode_checkUse (a, sRef_makePointer (a->sref), a->loc);
1488 uentry_setType (regArg, ctype_unknown);
1489 uentry_fixupSref (regArg);
1493 exprNode_checkCallModifyVal (a->sref, args, f, ret);
1507 voptgenerror (FLG_TYPE,
1508 message ("Format string for %q has %d arg%p, given %d",
1509 uentry_getName (fcn), i - argno, nargs - argno),
1515 /* no checking possible for compile-time unknown format strings */
1518 fileloc_free (formatloc);
1522 checkScanfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1523 exprNodeList args, exprNode ret, int argno)
1527 int nargs = exprNodeList_size (args);
1528 uentryList params = uentry_getParams (fcn);
1532 ** These should be ensured by checkSpecialFunction
1535 llassert (uentryList_size (params) == argno + 1);
1536 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1538 a = exprNodeList_getN (args, argno - 1);
1539 formatloc = fileloc_copy (exprNode_loc (a));
1541 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1542 && exprNode_knownStringValue (a))
1544 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1545 char *code = format;
1548 nargs = exprNodeList_size (args);
1550 while ((code = strchr (code, '%')) != NULL)
1552 char *origcode = code;
1553 char key = *(++code);
1554 ctype modtype = ctype_int;
1555 char modifier = '\0';
1556 bool modified = TRUE;
1557 bool ignore = FALSE;
1559 fileloc_addColumn (formatloc, code - ocode);
1562 ** this is based on ANSI standard library description of fscanf
1563 ** (from ANSI standard X3.159-1989, 4.9.6.1)
1566 /* '*' suppresses assignment (does not need match argument) */
1573 fileloc_incColumn (formatloc);
1576 /* ignore field width */
1577 while (isdigit ((int) key) != 0)
1580 fileloc_incColumn (formatloc);
1585 modtype = ctype_sint; /* short */
1587 fileloc_incColumn (formatloc);
1589 else if (key == 'l' || key == 'L')
1591 modtype = ctype_lint; /* long */
1595 fileloc_incColumn (formatloc);
1597 if (key == 'l' || key == 'L') {
1598 modtype = ctype_llint; /* long long */
1600 fileloc_incColumn (formatloc);
1608 /* now, key = type of conversion to apply */
1610 fileloc_incColumn (formatloc);
1624 message ("No argument corresponding to %q format "
1625 "code %d (%%%h): \"%s\"",
1626 uentry_getName (fcn),
1628 cstring_fromChars (format)),
1631 if (fileloc_isDefined (formatloc)
1632 && context_getFlag (FLG_SHOWCOL))
1635 (cstring_makeLiteral ("Corresponding format code"),
1643 a = exprNodeList_getN (args, i);
1646 if (!exprNode_isError (a))
1652 case '*': /* int argument for fieldwidth */
1653 expecttype = ctype_makePointer (ctype_int);
1654 *(--code) = '%'; /* convert it for next code */
1655 fileloc_subColumn (formatloc, 1);
1656 /*@switchbreak@*/ break;
1659 expecttype = ctype_makePointer (ctype_combine (ctype_uint, modtype));
1660 /*@switchbreak@*/ break;
1665 case 'X': /* unsigned int */
1666 expecttype = ctype_makePointer (ctype_combine (ctype_int, modtype));
1667 /*@switchbreak@*/ break;
1674 /* printf is double, scanf is float! */
1676 if (modifier == 'l')
1678 expecttype = ctype_makePointer (ctype_double);
1680 else if (modifier == 'L')
1682 expecttype = ctype_makePointer (ctype_ldouble);
1686 llassert (modifier == '\0');
1687 expecttype = ctype_makePointer (ctype_float);
1689 /*@switchbreak@*/ break;
1691 case 'c': /* int converted to char (check its a char?) */
1692 expecttype = ctype_makePointer (ctype_makeConj (ctype_char, ctype_uchar));
1693 /*@switchbreak@*/ break;
1695 case 's': /* string */
1696 expecttype = ctype_string;
1697 /*@switchbreak@*/ break;
1701 while (((key = *(++code)) != ']')
1704 fileloc_incColumn (formatloc);
1710 (message ("Bad character set format: %s",
1711 cstring_fromChars (origcode)));
1714 expecttype = ctype_string;
1715 /*@switchbreak@*/ break;
1717 case 'p': /* pointer */
1718 expecttype = ctype_unknown;
1720 /*@switchbreak@*/ break;
1722 case 'n': /* pointer to int, modified by call! */
1723 expecttype = ctype_makePointer (ctype_int);
1724 /*@switchbreak@*/ break;
1727 expecttype = ctype_unknown;
1731 message ("Unrecognized format code: %s",
1732 cstring_fromChars (origcode)),
1733 fileloc_isDefined (formatloc)
1734 ? formatloc : g_currentloc);
1736 /*@switchbreak@*/ break;
1739 if (!(exprNode_matchArgType (expecttype, a)))
1741 if (ctype_isVoidPointer (expecttype)
1742 && ctype_isRealAbstract (a->typ)
1743 && (context_getFlag (FLG_ABSTVOIDP)))
1749 if (modifier != '\0')
1751 if (llgenformattypeerror
1752 (expecttype, exprNode_undefined,
1754 message ("Format argument %d to %q (%%%h%h) expects "
1757 uentry_getName (fcn),
1760 a->typ, exprNode_unparse (a)),
1763 if (fileloc_isDefined (formatloc)
1764 && context_getFlag (FLG_SHOWCOL))
1767 (cstring_makeLiteral
1768 ("Corresponding format code"),
1776 if (llgenformattypeerror
1777 (expecttype, exprNode_undefined,
1779 message ("Format argument %d to %q (%%%h) expects "
1782 uentry_getName (fcn),
1784 a->typ, exprNode_unparse (a)),
1787 if (fileloc_isDefined (formatloc)
1788 && context_getFlag (FLG_SHOWCOL))
1791 (cstring_makeLiteral
1792 ("Corresponding format code"),
1800 uentry_setType (outArg, expecttype);
1801 checkOneArg (outArg, a, f, FALSE, i+1, nargs);
1802 uentry_setType (outArg, ctype_unknown);
1803 uentry_fixupSref (outArg);
1807 exprNode_checkCallModifyVal (a->sref, args, f, ret);
1812 /* a->sref = defref; */
1822 voptgenerror (FLG_TYPE,
1823 message ("Format string for %q has %d arg%p, given %d",
1824 uentry_getName (fcn), i - argno, nargs - argno),
1830 /* no checking possible for compile-time unknown format strings */
1833 fileloc_free (formatloc);
1837 checkMessageArgs (/*@notnull@*/ /*@dependent@*/ exprNode f,
1840 /*@unused@*/ int argno)
1843 ** the last argument before the elips is the format string
1846 int nargs = exprNodeList_size (args);
1851 a = exprNodeList_getN (args, argno - 1);
1852 formatloc = fileloc_copy (exprNode_loc (a));
1854 if (ctype_isUnknown (cstringType)) {
1855 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
1857 cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
1861 if (ctype_isUnknown (ctypeType)) {
1862 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
1864 ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
1868 if (ctype_isUnknown (filelocType)) {
1869 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
1871 filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
1875 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1876 && exprNode_knownStringValue (a))
1878 cstring format = multiVal_forceString (exprNode_getValue (a));
1879 char *code = cstring_toCharsSafe (format);
1882 nargs = exprNodeList_size (args);
1884 while ((code = strchr (code, '%')) != NULL)
1886 char *origcode = code;
1887 char key = *(++code);
1888 bool isOnly = FALSE;
1890 fileloc_addColumn (formatloc, code - ocode);
1892 while (key >= '0' && key <= '9')
1895 fileloc_incColumn (formatloc);
1899 fileloc_incColumn (formatloc);
1912 message ("Message missing format arg %d (%%%h): \"%s\"",
1913 i + 1, key, format),
1919 a = exprNodeList_getN (args, i);
1923 if (!exprNode_isError (a))
1927 /*@-loopswitchbreak@*/
1933 expecttype = ctype_char; break;
1935 expecttype = cstringType; break;
1937 expecttype = cstringType; isOnly = TRUE; break;
1939 expecttype = cstringType; isOnly = TRUE; break;
1940 case 'd': expecttype = ctype_int; break;
1941 case 'u': expecttype = ctype_uint; break;
1942 case 'w': expecttype = ctype_ulint; break;
1943 case 'f': expecttype = ctype_float; break;
1944 case 'b': expecttype = ctype_bool; break;
1945 case 't': expecttype = ctypeType; break;
1946 case 'l': expecttype = filelocType; break;
1947 case 'p': /* a wee bit of a hack methinks */
1948 expecttype = ctype_int;
1950 case 'r': expecttype = ctype_bool; break;
1952 expecttype = ctype_unknown;
1955 message ("Unrecognized format code: %s",
1956 cstring_fromChars (origcode)),
1957 fileloc_isDefined (formatloc)
1958 ? formatloc : g_currentloc);
1961 /*@=loopswitchbreak@*/
1963 if (!(exprNode_matchArgType (expecttype, a)))
1965 if (ctype_isVoidPointer (expecttype)
1966 && ctype_isRealAbstract (a->typ)
1967 && (context_getFlag (FLG_ABSTVOIDP)))
1973 if (llgenformattypeerror
1974 (expecttype, exprNode_undefined,
1976 message ("Format argument %d to %q (%%%h) expects "
1979 uentry_getName (fcn),
1981 a->typ, exprNode_unparse (a)),
1984 if (fileloc_isDefined (formatloc)
1985 && context_getFlag (FLG_SHOWCOL))
1988 (cstring_makeLiteral
1989 ("Corresponding format code"),
1996 if (ctype_equal (expecttype, cstringType))
2000 checkOneArg (csOnlyArg, a, f, FALSE, i+1, nargs);
2001 uentry_fixupSref (csOnlyArg);
2005 checkOneArg (csArg, a, f, FALSE, i+1, nargs);
2006 uentry_fixupSref (csArg);
2011 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
2012 uentry_fixupSref (regArg);
2021 voptgenerror (FLG_TYPE,
2022 message ("Format string for %q has %d arg%p, given %d",
2023 uentry_getName (fcn), i - argno, nargs -argno),
2029 /* no checking possible for compile-time unknown format strings */
2032 fileloc_free (formatloc);
2036 checkExpressionDefinedAux (/*@notnull@*/ exprNode e1,
2037 /*@notnull@*/ exprNode e2,
2043 bool hadUncon = FALSE;
2045 if (sRef_isGlobal (sRef_getRootBase (e1->sref)) &&
2046 sRefSet_hasUnconstrained (sets2))
2049 (FLG_EVALORDERUNCON,
2051 ("Expression may have undefined behavior (%q used in right operand "
2052 "may set global variable %q used in left operand): %s %s %s",
2053 sRefSet_unparseUnconstrained (sets2),
2054 sRef_unparse (sRef_getRootBase (e1->sref)),
2055 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2059 if (sRef_isGlobal (sRef_getRootBase (e2->sref)) &&
2060 sRefSet_hasUnconstrained (sets1))
2063 (FLG_EVALORDERUNCON,
2065 ("Expression has undefined behavior (%q used in left operand "
2066 "may set global variable %q used in right operand): %s %s %s",
2067 sRefSet_unparseUnconstrained (sets1),
2068 sRef_unparse (e2->sref),
2069 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2073 sRefSet_realElements (e1->uses, sr)
2075 if (sRef_isMeaningful (sr) && sRefSet_member (sets2, sr))
2080 ("Expression has undefined behavior (left operand uses %q, "
2081 "modified by right operand): %s %s %s",
2083 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2086 } end_sRefSet_realElements;
2088 sRefSet_realElements (sets1, sr)
2090 if (sRef_isMeaningful (sr))
2092 if (sRef_same (sr, e2->sref))
2097 ("Expression has undefined behavior (value of right operand "
2098 "modified by left operand): %s %s %s",
2099 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2102 else if (sRefSet_member (e2->uses, sr))
2107 ("Expression has undefined behavior (left operand modifies %q, "
2108 "used by right operand): %s %s %s",
2110 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2115 if (sRefSet_member (sets2, sr))
2117 if (sRef_isUnconstrained (sr))
2125 hadUncon = optgenerror
2126 (FLG_EVALORDERUNCON,
2128 ("Expression may have undefined behavior. Left operand "
2129 "calls %q; right operand calls %q. The unconstrained "
2130 "functions may modify global state used by "
2131 "the other operand): %s %s %s",
2132 sRefSet_unparseUnconstrained (sets1),
2133 sRefSet_unparseUnconstrained (sets2),
2134 exprNode_unparse (e1), lltok_unparse (op),
2135 exprNode_unparse (e2)),
2144 ("Expression has undefined behavior (both "
2145 "operands modify %q): %s %s %s",
2147 exprNode_unparse (e1),
2148 lltok_unparse (op), exprNode_unparse (e2)),
2154 } end_sRefSet_realElements;
2157 static void checkExpressionDefined (exprNode e1, exprNode e2, lltok op)
2159 bool hasError = FALSE;
2161 if (exprNode_isError (e1) || exprNode_isError (e2))
2166 if (sRefSet_member (e2->sets, e1->sref))
2168 if (e2->kind == XPR_CALL)
2174 hasError = optgenerror
2176 message ("Expression has undefined behavior "
2177 "(value of left operand is modified "
2178 "by right operand): %s %s %s",
2179 exprNode_unparse (e1), lltok_unparse (op),
2180 exprNode_unparse (e2)),
2185 if (context_getFlag (FLG_EVALORDERUNCON))
2187 if (sRefSet_member (e2->msets, e1->sref))
2189 if (e2->kind == XPR_CALL)
2195 hasError = optgenerror
2198 ("Expression has undefined behavior (value of left "
2199 "operand may be modified by right operand): %s %s %s",
2200 exprNode_unparse (e1), lltok_unparse (op),
2201 exprNode_unparse (e2)),
2209 checkExpressionDefinedAux (e1, e2, e1->sets, e2->sets, op, FLG_EVALORDER);
2211 if (context_maybeSet (FLG_EVALORDERUNCON))
2213 checkExpressionDefinedAux (e1, e2, e1->msets,
2214 e2->msets, op, FLG_EVALORDERUNCON);
2219 static void checkSequencing (exprNode p_f, exprNodeList p_args);
2222 checkArgsReal (uentry fcn, /*@dependent@*/ exprNode f, uentryList cl,
2223 exprNodeList args, bool isIter, exprNode ret)
2227 if (!exprNode_isError (f))
2229 if (!uentryList_isMissingParams (cl))
2231 int nargs = exprNodeList_size (args);
2232 int expectargs = uentryList_size (cl);
2236 if (expectargs == 0)
2244 message ("Iter %q invoked with %d args, "
2246 uentry_getName (fcn),
2254 message ("Function %s called with %d args, "
2256 exprNode_unparse (f), nargs),
2263 last = uentry_getType (uentryList_getN (cl, expectargs - 1));
2265 exprNodeList_reset (args);
2267 uentryList_elements (cl, current)
2269 ctype ct = uentry_getType (current);
2272 if (ctype_isElips (ct))
2275 ** do special checking for printf/scanf library functions
2277 ** this is kludgey code, just for handling the special case
2281 if (uentry_isPrintfLike (fcn))
2283 checkPrintfArgs (f, fcn, args, ret, i);
2286 else if (uentry_isScanfLike (fcn))
2288 checkScanfArgs (f, fcn, args, ret, i);
2291 else if (uentry_isMessageLike (fcn))
2293 checkMessageArgs (f, fcn, args, i);
2298 llassert (!uentry_isSpecialFunction (fcn));
2301 nargs = expectargs; /* avoid errors */
2306 if (i >= nargs) break;
2308 a = exprNodeList_current (args);
2309 exprNodeList_advance (args);
2313 if (exprNode_isError (a))
2320 probably necessary? I'm not sure about this one
2321 checkMacroParen (a);
2324 f->guards = guardSet_union (f->guards, a->guards);
2326 DPRINTF (("match arg: %s / %s", ctype_unparse (ct), ctype_unparse (a->typ)));
2328 if (!(exprNode_matchArgType (ct, a)))
2330 DPRINTF (("Args mismatch!"));
2332 if (ctype_isVoidPointer (ct)
2333 && (ctype_isPointer (a->typ)
2334 && (ctype_isRealAbstract (ctype_baseArrayPtr (a->typ)))))
2339 ("Pointer to abstract type (%t) used "
2341 "(arg %d to %q): %s",
2343 uentry_getName (fcn),
2344 exprNode_unparse (a)),
2352 (ct, exprNode_undefined,
2355 ("Iter %q expects arg %d to "
2356 "be %t gets %t: %s",
2357 uentry_getName (fcn),
2358 i, ct, a->typ, exprNode_unparse (a)),
2369 ("Function %q expects arg %d to be %t gets %t: %s",
2370 uentry_getName (fcn),
2371 i, ct, a->typ, exprNode_unparse (a)),
2374 DPRINTF (("Types: %s / %s",
2376 ctype_unparse (a->typ)));
2380 ** Clear null marker for abstract types.
2381 ** (It is not revealed, so suppress future messages.)
2384 if (ctype_isAbstract (a->typ))
2386 sRef_setNullUnknown (exprNode_getSref (a), a->loc);
2393 } end_uentryList_elements ;
2396 if (expectargs != nargs) /* note: not != since we may have ... */
2398 if (ctype_isElips (last))
2402 message ("Function %s called with %d args, expects at least %d",
2403 exprNode_unparse (f),
2404 nargs, expectargs - 1),
2413 message ("Iter %q invoked with %d args, expects %d",
2414 uentry_getName (fcn), nargs, expectargs),
2421 message ("Function %s called with %d args, expects %d",
2422 exprNode_unparse (f),
2435 ** Check for undefined code sequences in function arguments:
2437 ** one parameter sets something used by another parameter
2438 ** one parameter sets something set by another parameter
2442 checkSequencingOne (exprNode f, exprNodeList args,
2443 /*@notnull@*/ exprNode el, int argno)
2446 ** Do second loop, iff +undefunspec
2450 int numloops = context_maybeSet (FLG_EVALORDERUNCON) ? 2 : 1;
2452 for (checkloop = 0; checkloop < numloops; checkloop++)
2458 thissets = el->sets;
2462 llassert (checkloop == 1);
2463 thissets = el->msets;
2466 sRefSet_realElements (thissets, thisset)
2470 /*@access exprNodeList@*/
2471 for (j = 0; j < args->nelements; j++)
2473 exprNode jl = args->elements[j];
2474 int thisargno = j + 1;
2476 if (thisargno != argno && exprNode_isDefined (jl))
2478 sRefSet otheruses = jl->uses;
2480 if (sRef_isGlobal (sRef_getRootBase (jl->sref)) &&
2481 sRefSet_hasUnconstrained (thissets))
2484 (FLG_EVALORDERUNCON,
2487 ("%q used in argument %d may set "
2488 "global variable %q used by argument %d: %s(%q)",
2489 cstring_capitalizeFree (sRefSet_unparseUnconstrained (thissets)),
2492 sRef_unparse (sRef_getRootBase (jl->sref)),
2494 exprNode_unparse (f), exprNodeList_unparse (args)),
2498 if (sRefSet_member (otheruses, thisset))
2500 if (sRef_isUnconstrained (thisset))
2503 (FLG_EVALORDERUNCON,
2505 ("Unconstrained functions used in arguments %d (%q) "
2506 "and %d (%s) may modify "
2507 "or use global state in undefined way: %s(%q)",
2509 sRefSet_unparseUnconstrainedPlain (otheruses),
2511 sRef_unconstrainedName (thisset),
2512 exprNode_unparse (f),
2513 exprNodeList_unparse (args)),
2521 ("Argument %d modifies %q, used by argument %d "
2522 "(order of evaluation of actual parameters is "
2523 "undefined): %s(%q)",
2524 argno, sRef_unparse (thisset), thisargno,
2525 exprNode_unparse (f), exprNodeList_unparse (args)),
2531 sRefSet othersets = jl->sets;
2533 if (sRefSet_member (othersets, thisset))
2535 if (sRef_isUnconstrained (thisset))
2538 (FLG_EVALORDERUNCON,
2540 ("Unconstrained functions used in "
2541 "arguments %d (%q) and %d (%s) may modify "
2542 "or use global state in undefined way: %s(%q)",
2544 sRefSet_unparseUnconstrainedPlain (othersets),
2546 sRef_unconstrainedName (thisset),
2547 exprNode_unparse (f), exprNodeList_unparse (args)),
2555 ("Argument %d modifies %q, set by argument %d (order of"
2556 " evaluation of actual parameters is undefined): %s(%q)",
2557 argno, sRef_unparse (thisset), thisargno,
2558 exprNode_unparse (f), exprNodeList_unparse (args)),
2565 /*@noaccess exprNodeList@*/
2566 } end_sRefSet_realElements;
2571 checkSequencing (exprNode f, exprNodeList args)
2573 if (exprNodeList_size (args) > 1)
2578 /*@access exprNodeList*/
2580 for (i = 0; i < args->nelements; i++)
2582 el = args->elements[i];
2584 if (!exprNode_isError (el))
2586 checkSequencingOne (f, args, el, i + 1);
2589 /*@noaccess exprNodeList*/
2594 ** requires le = exprNode_getUentry (f)
2598 checkGlobMods (/*@notnull@*/ /*@dependent@*/ exprNode f,
2599 uentry le, exprNodeList args,
2600 /*@notnull@*/ exprNode ret, int specialArgs)
2602 bool isSpec = FALSE;
2603 bool hasMods = FALSE;
2605 globSet usesGlobs = globSet_undefined;
2606 sRefSet mods = sRefSet_undefined;
2607 bool freshMods = FALSE;
2608 uentryList params = uentryList_undefined;
2611 ** check globals and modifies
2616 if (!uentry_isValid (le))
2618 ctype fr = ctype_realType (f->typ);
2620 if (ctype_isFunction (fr))
2622 params = ctype_argsFunction (fr);
2626 params = uentryList_missingParams;
2629 if (!context_getFlag (FLG_MODNOMODS)
2630 && !context_getFlag (FLG_GLOBUNSPEC))
2632 checkUnspecCall (f, params, args);
2638 fname = uentry_rawName (le);
2642 if (uentry_isFunction (le))
2644 params = uentry_getParams (le);
2645 mods = uentry_getMods (le);
2646 hasMods = uentry_hasMods (le);
2647 usesGlobs = uentry_getGlobs (le);
2648 isSpec = uentry_isSpecified (le);
2650 else /* not a function */
2652 ctype ct = ctype_realType (uentry_getType (le));
2654 llassertprint (uentry_isVar (le) && ctype_isFunction (ct),
2655 ("checkModGlobs: uentry not a function: %s",
2656 uentry_unparse (le)));
2658 params = ctype_argsFunction (ct);
2668 globSet_allElements (usesGlobs, el)
2670 if (sRef_isValid (el))
2672 if (sRef_isInternalState (el) || sRef_isSystemState (el))
2674 context_usedGlobal (el);
2675 exprNode_checkUse (f, el, f->loc);
2677 if (context_checkInternalUse ())
2679 if (!context_globAccess (el))
2681 if (sRef_isSystemState (el)
2682 && !context_getFlag (FLG_MODFILESYSTEM))
2691 ("Called procedure %s may access %q, but "
2692 "globals list does not include globals %s",
2693 exprNode_unparse (f),
2695 cstring_makeLiteralTemp (sRef_isInternalState (el)
2703 else if (sRef_isNothing (el) || sRef_isSpecState (el))
2709 uentry gle = sRef_getUentry (el);
2710 sRef sr = sRef_updateSref (el);
2712 if (sRef_isUndefGlob (el))
2714 sRef_setDefined (sr, f->loc);
2715 exprNode_checkSet (f, sr);
2723 if (sRef_isAllocated (el))
2725 exprNode_checkSet (f, sr);
2729 if (sRef_isStateUndefined (sr))
2734 ("%s %q used by function undefined before call: %s",
2735 sRef_getScopeName (sr),
2737 exprNode_unparse (f)),
2739 sRef_setDefined (sr, f->loc);
2741 exprNode_checkUse (f, sr, f->loc);
2744 checkGlobUse (gle, TRUE, f);
2747 if (sRef_isKilledGlob (el))
2749 sRef_kill (sr, f->loc);
2750 context_usedGlobal (sr);
2754 } end_globSet_allElements;
2760 if (context_hasMods () || context_getFlag (FLG_MODNOMODS))
2762 sRefSet smods = sRefSet_undefined;
2765 ** NEED to check for modifies anything
2769 ** check each sRef that called function modifies (ml), is
2775 sRefSet_allElements (mods, s) /* s is something which may be modified */
2777 if (sRef_isKindSpecial (s))
2779 if (sRef_isSpecInternalState (s))
2781 if (context_getFlag (FLG_MODINTERNALSTRICT))
2783 exprNode_checkCallModifyVal (s, args, f, ret);
2787 sRefSet mmods = context_modList ();
2789 sRefSet_allElements (mmods, el)
2791 if (sRef_isInternalState (el))
2793 sRef_setModified (el);
2795 } end_sRefSet_allElements ;
2800 exprNode_checkCallModifyVal (s, args, f, ret);
2805 sRef rb = sRef_getRootBase (s);
2807 if (sRef_isGlobal (rb))
2809 context_usedGlobal (rb);
2812 if (sRef_isFileStatic (s)
2813 && !fileId_equal (fileloc_fileId (f->loc),
2814 fileloc_fileId (uentry_whereDefined (le))))
2816 smods = sRefSet_insert (smods, s);
2820 exprNode_checkCallModifyVal (s, args, f, ret);
2823 } end_sRefSet_allElements;
2828 ** Static elements in modifies set can have nasty consequences.
2829 ** (I think...have not been able to reproduce a possible bug.)
2832 if (!sRefSet_isDefined (smods))
2834 mods = sRefSet_newCopy (mods);
2837 sRefSet_allElements (smods, el)
2839 bool res = sRefSet_delete (mods, el);
2842 } end_sRefSet_allElements;
2844 sRefSet_free (smods);
2849 else if (sRefSet_isDefined (mods))
2850 { /* just check observers */
2853 sRefSet_allElements (mods, s) /* s is something which may be modified */
2855 sRef rb = sRef_getRootBase (s);
2859 if (sRef_isParam (rb))
2861 sRef b = sRef_fixBaseParam (s, args);
2863 if (sRef_isObserver (b))
2865 exprNode e = exprNodeList_nth (args, sRef_getParam (rb));
2869 message ("Function call may modify observer%q: %s",
2870 sRef_unparsePreOpt (b), exprNode_unparse (e)),
2873 sRef_showExpInfo (b);
2877 } end_sRefSet_allElements;
2881 if (!hasMods) /* no specified modifications */
2883 if (context_getFlag (FLG_MODOBSERVERUNCON))
2885 exprNodeList_elements (args, e)
2887 if (exprNode_isDefined (e))
2889 sRef s = exprNode_getSref (e);
2891 if (sRef_isObserver (s)
2892 && ctype_isMutable (sRef_getType (s)))
2895 (FLG_MODOBSERVERUNCON,
2897 ("Call to unconstrained function %s may modify observer%q: %s",
2898 exprNode_unparse (f),
2899 sRef_unparsePreOpt (s), exprNode_unparse (e)),
2902 sRef_showExpInfo (s);
2906 } end_exprNodeList_elements;
2911 checkAnyCall (f, fname, params, args, hasMods, mods, isSpec, specialArgs);
2913 ret->uses = sRefSet_union (ret->uses, f->uses);
2914 ret->sets = sRefSet_union (ret->sets, f->sets);
2915 ret->msets = sRefSet_union (ret->msets, f->msets);
2920 ** Spurious errors reported, because lclint can't tell
2921 ** mods must be fresh if freshMods is true.
2924 /*@i@*/ sRefSet_free (mods);
2930 void checkGlobUse (uentry glob, bool isCall, /*@notnull@*/ exprNode e)
2932 if (uentry_isVar (glob))
2934 if (context_inFunctionLike ())
2936 sRef sr = uentry_getSref (glob);
2938 context_usedGlobal (sr);
2940 if (context_checkGlobUse (glob))
2942 if (!context_globAccess (sr))
2948 message ("Called procedure %s may access %s %q",
2949 exprNode_unparse (e),
2950 sRef_unparseScope (sr),
2951 uentry_getName (glob)),
2958 message ("Undocumented use of %s %s",
2959 sRef_unparseScope (sr),
2960 exprNode_unparse (e)),
2969 llbug (message ("Global not variable: %q", uentry_unparse (glob)));
2973 static /*@only@*/ exprNode
2974 functionCallSafe (/*@only@*/ /*@notnull@*/ exprNode f,
2975 ctype t, /*@keep@*/ exprNodeList args)
2977 /* requires f is a non-error exprNode, with type function */
2978 cstring fname = exprNode_unparse (f);
2979 uentry le = exprNode_getUentry (f);
2980 exprNode ret = exprNode_createPartialCopy (f);
2985 ret->typ = ctype_returnValue (t);
2986 ret->kind = XPR_CALL;
2988 ret->edata = exprData_makeCall (f, args);
2991 ** Order of these steps is very important!
2993 ** Must check for argument dependencies before messing up uses and sets.
2996 if (context_getFlag (FLG_EVALORDER))
2998 exprNodeList_elements (args, current)
3000 if (exprNode_isDefined (current))
3002 exprNode_addUse (current, current->sref);
3004 } end_exprNodeList_elements;
3006 if (context_maybeSet (FLG_EVALORDER) || context_maybeSet (FLG_EVALORDERUNCON))
3008 checkSequencing (f, args);
3011 exprNodeList_elements (args, current)
3013 if (exprNode_isDefined (current) && sRef_isMeaningful (current->sref))
3015 exprNode_addUse (ret, sRef_makeDerived (current->sref));
3017 } end_exprNodeList_elements ;
3020 special = checkArgs (le, f, t, args, ret);
3021 checkGlobMods (f, le, args, ret, special);
3025 if (uentry_isValid (le)
3026 && (uentry_isFunction (le)
3027 || (uentry_isVariable (le)
3028 && ctype_isFunction (uentry_getType (le)))))
3030 exitkind exk = uentry_getExitCode (le);
3032 /* f->typ is already set to the return type */
3034 ret->sref = uentry_returnedRef (le, args);
3036 if (uentry_isFunction (le) && exprNodeList_size (args) >= 1)
3038 qual nullPred = uentry_nullPred (le);
3040 if (qual_isTrueNull (nullPred))
3042 exprNode arg = exprNodeList_head (args);
3044 if (exprNode_isDefined (arg))
3046 ret->guards = guardSet_addFalseGuard (ret->guards, arg->sref);
3049 else if (qual_isFalseNull (nullPred))
3051 exprNode arg = exprNodeList_head (args);
3053 if (exprNode_isDefined (arg))
3055 ret->guards = guardSet_addTrueGuard (ret->guards, arg->sref);
3060 llassert (qual_isUnknown (nullPred));
3064 if (exitkind_isConditionalExit (exk))
3068 ** if (arg0) then { exit! } else { ; }
3070 ** if (arg0) then { ; } else { exit! }
3075 llassert (!exprNodeList_isEmpty (args));
3076 firstArg = exprNodeList_head (args);
3078 if (exprNode_isDefined (firstArg)
3079 && !guardSet_isEmpty (firstArg->guards))
3081 usymtab_trueBranch (guardSet_undefined);
3082 usymtab_altBranch (guardSet_undefined);
3084 if (exitkind_isTrueExit (exk))
3086 usymtab_popBranches (firstArg,
3087 exprNode_makeMustExit (),
3089 TRUE, TRUEEXITCLAUSE);
3093 usymtab_popBranches (firstArg,
3095 exprNode_makeMustExit (),
3096 TRUE, FALSEEXITCLAUSE);
3100 ret->exitCode = XK_MAYEXIT;
3102 else if (exitkind_mustExit (exk))
3104 ret->exitCode = XK_MUSTEXIT;
3106 else if (exitkind_couldExit (exk))
3108 ret->exitCode = XK_MAYEXIT;
3115 if (cstring_equalLit (fname, "exit"))
3117 if (exprNodeList_size (args) == 1)
3119 exprNode arg = exprNodeList_head (args);
3121 if (exprNode_isDefined (arg) && exprNode_knownIntValue (arg))
3123 long int val = multiVal_forceInt (exprNode_getValue (arg));
3130 ("Argument to exit has implementation defined behavior: %s",
3131 exprNode_unparse (arg)),
3132 exprNode_loc (arg));
3141 exprNode_checkSetAny (ret, uentry_rawName (le));
3148 ** this is yucky! should keep the uentry as part of exprNode!
3151 /*@observer@*/ uentry
3152 exprNode_getUentry (exprNode e)
3154 if (exprNode_isError (e))
3156 return uentry_undefined;
3160 cstring s = exprNode_rootVarName (e);
3161 uentry ue = usymtab_lookupSafe (s);
3168 exprNode_makeInitBlock (lltok brace, /*@only@*/ exprNodeList inits)
3170 exprNode ret = exprNode_createPlain (ctype_unknown);
3172 ret->kind = XPR_INITBLOCK;
3173 ret->edata = exprData_makeCall (exprNode_undefined, inits);
3174 ret->loc = fileloc_update (ret->loc, lltok_getLoc (brace));
3180 exprNode_functionCall (/*@only@*/ exprNode f, /*@only@*/ exprNodeList args)
3186 if (exprNode_isUndefined (f))
3189 exprNodeList_free (args);
3190 return exprNode_undefined;
3193 t = exprNode_getType (f);
3195 if (sRef_isLocalVar (f->sref))
3197 exprNode_checkUse (f, f->sref, f->loc);
3199 if (sRef_possiblyNull (f->sref))
3201 if (!usymtab_isGuarded (f->sref))
3203 if (optgenerror (FLG_NULLDEREF,
3204 message ("Function call using %s pointer %q",
3205 sRef_nullMessage (f->sref),
3206 sRef_unparse (f->sref)),
3209 sRef_showNullInfo (f->sref);
3210 sRef_setNullError (f->sref);
3218 if (ctype_isRealFunction (t))
3220 exprNode ret = functionCallSafe (f, t, args);
3224 else if (ctype_isUnknown (t))
3226 exprNode ret = exprNode_createPartialCopy (f);
3232 exprNodeList_elements (args, current)
3234 if (exprNode_isDefined (current))
3236 exprNode_checkUse (ret, current->sref, ret->loc);
3239 ** also, anything derivable from current->sref may be used
3242 exprNode_addUse (ret, sRef_makeDerived (current->sref));
3243 exprNode_mergeUSs (ret, current);
3245 } end_exprNodeList_elements;
3247 ret->edata = exprData_makeCall (f, args);
3248 ret->kind = XPR_CALL;
3250 tstring = cstring_copy (exprNode_unparse (f));
3252 cstring_markOwned (tstring);
3253 exprNode_checkSetAny (ret, tstring);
3259 voptgenerror (FLG_TYPE,
3260 message ("Call to non-function (type %t): %s", t,
3261 exprNode_unparse (f)),
3264 exprNodeList_free (args);
3266 return (exprNode_makeError ());
3271 exprNode_fieldAccess (/*@only@*/ exprNode s, /*@only@*/ cstring f)
3273 exprNode ret = exprNode_createPartialCopy (s);
3275 ret->kind = XPR_FACCESS;
3277 if (exprNode_isError (s))
3279 ret->edata = exprData_makeField (s, f);
3284 ctype t = exprNode_getType (s);
3285 ctype tr = ctype_realType (t);
3287 checkMacroParen (s);
3289 ret->edata = exprData_makeField (s, f);
3291 if (ctype_isStructorUnion (tr))
3293 uentry tf = uentryList_lookupField (ctype_getFields (tr), f);
3295 if (uentry_isUndefined (tf))
3297 voptgenerror (FLG_TYPE,
3298 message ("Access non-existent field %s of %t: %s", f, t,
3299 exprNode_unparse (ret)),
3306 uentry_setUsed (tf, exprNode_loc (ret));
3308 ret->typ = uentry_getType (tf);
3309 checkSafeUse (ret, s->sref);
3311 ret->sref = sRef_makeField (s->sref, uentry_rawName (tf));
3315 else /* isStructorUnion */
3317 if (ctype_isRealAbstract (tr))
3321 message ("Access field of abstract type (%t): %s.%s",
3322 t, exprNode_unparse (s), f),
3324 ret->typ = ctype_unknown;
3328 if (ctype_isKnown (tr))
3333 ("Access field of non-struct or union (%t): %s.%s",
3334 t, exprNode_unparse (s), f),
3337 ret->typ = ctype_unknown;
3341 cstring sn = cstring_copy (f);
3343 checkSafeUse (ret, s->sref);
3344 cstring_markOwned (sn);
3345 ret->sref = sRef_makeField (s->sref, sn);
3357 exprNode_addParens (/*@only@*/ lltok lpar, /*@only@*/ exprNode e)
3359 exprNode ret = exprNode_createPartialCopy (e);
3361 ret->loc = fileloc_update (ret->loc, lltok_getLoc (lpar));
3362 ret->kind = XPR_PARENS;
3363 ret->edata = exprData_makeUop (e, lpar);
3365 if (!exprNode_isError (e))
3367 ret->exitCode = e->exitCode;
3368 ret->canBreak = e->canBreak;
3369 ret->mustBreak = e->mustBreak;
3370 ret->isJumpPoint = e->isJumpPoint;
3371 ret->sref = e->sref;
3378 exprNode_arrowAccess (/*@only@*/ exprNode s, /*@only@*/ cstring f)
3380 exprNode ret = exprNode_createPartialCopy (s);
3382 ret->edata = exprData_makeField (s, f);
3383 ret->kind = XPR_ARROW;
3385 if (exprNode_isError (s))
3391 ctype t = exprNode_getType (s);
3392 ctype tr = ctype_realType (t);
3394 checkMacroParen (s);
3396 (void) ctype_fixArrayPtr (tr); /* REWRITE THIS */
3398 if (ctype_isRealPointer (tr))
3400 ctype b = ctype_realType (ctype_baseArrayPtr (tr));
3402 if (ctype_isStructorUnion (b))
3404 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
3406 if (sRef_isKnown (s->sref) && sRef_possiblyNull (s->sref))
3408 if (!usymtab_isGuarded (s->sref) && !context_inProtectVars ())
3412 message ("Arrow access from %s pointer%q: %s",
3413 sRef_nullMessage (s->sref),
3414 sRef_unparsePreOpt (s->sref),
3415 exprNode_unparse (ret)),
3418 sRef_showNullInfo (s->sref);
3419 sRef_setNullError (s->sref);
3424 if (uentry_isUndefined (fentry))
3428 message ("Access non-existent field %s of %t: %s",
3429 f, t, exprNode_unparse (ret)),
3431 ret->typ = ctype_unknown;
3438 ** was safeUse: shouldn't be safe!
3441 ** rec must be defined,
3442 ** *rec must be allocated
3443 ** rec->field need only be defined it if is an rvalue
3446 uentry_setUsed (fentry, exprNode_loc (ret));
3447 ret->typ = uentry_getType (fentry);
3449 exprNode_checkUse (ret, s->sref, s->loc);
3451 /* exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc); */
3452 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
3456 else /* Pointer to something that is not a struct or union*/
3458 if (ctype_isRealAbstract (tr))
3460 ctype xrt = ctype_forceRealType (tr);
3464 message ("Arrow access field of abstract type (%t): %s->%s",
3465 t, exprNode_unparse (s), f),
3469 ** Set the state correctly, as if the abstraction is broken.
3472 if (ctype_isRealPointer (xrt) &&
3473 (b = ctype_realType (ctype_baseArrayPtr (xrt)),
3474 ctype_isStructorUnion (b)))
3476 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
3477 ret->typ = uentry_getType (fentry);
3478 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
3482 ret->typ = ctype_unknown;
3483 ret->sref = sRef_undefined;
3486 else /* not a struct, union or abstract */
3488 if (ctype_isUnknown (tr)) {
3489 cstring sn = cstring_copy (f);
3491 DPRINTF (("Here: %s", exprNode_unparse (s)));
3493 exprNode_checkUse (ret, s->sref, s->loc);
3494 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
3496 cstring_markOwned (sn);
3497 ret->sref = sRef_makeArrow (s->sref, sn);
3499 ret->kind = XPR_ARROW;
3504 message ("Arrow access field of non-struct or union "
3505 "pointer (%t): %s->%s",
3506 t, exprNode_unparse (s), f),
3509 ret->typ = ctype_unknown;
3510 ret->sref = sRef_undefined;
3515 else /* its not a pointer */
3517 if (!ctype_isUnknown (tr))
3521 message ("Arrow access of non-pointer (%t): %s->%s",
3522 t, exprNode_unparse (s), f),
3525 ret->typ = ctype_unknown;
3526 ret->sref = sRef_undefined;
3530 cstring sn = cstring_copy (f);
3532 DPRINTF (("Here: %s", exprNode_unparse (s)));
3534 exprNode_checkUse (ret, s->sref, s->loc);
3535 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
3537 cstring_markOwned (sn);
3538 ret->sref = sRef_makeArrow (s->sref, sn);
3540 ret->kind = XPR_ARROW;
3551 ** only postOp's in C: i++ and i--
3555 exprNode_postOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
3557 /* check modification also */
3558 /* cstring opname = lltok_unparse (op);*/
3560 exprNode ret = exprNode_createPartialCopy (e);
3562 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
3563 ret->kind = XPR_POSTOP;
3564 ret->edata = exprData_makeUop (e, op);
3566 if (!exprNode_isDefined (e))
3571 checkMacroParen (e);
3573 exprNode_checkUse (ret, e->sref, e->loc);
3574 exprNode_checkSet (ret, e->sref);
3576 t = exprNode_getType (e);
3578 if (sRef_isUnsafe (e->sref))
3580 voptgenerror (FLG_MACROPARAMS,
3581 message ("Operand of %s is macro parameter (non-functional): %s%s",
3582 lltok_unparse (op), exprNode_unparse (e), lltok_unparse (op)),
3584 sRef_makeSafe (e->sref);
3585 sRef_makeSafe (ret->sref);
3588 if (ctype_isForceRealNumeric (&t) || ctype_isRealAP (t))
3594 if (ctype_isRealAbstract (t))
3598 message ("Operand of %s is abstract type (%t): %s",
3599 lltok_unparse (op), t, exprNode_unparse (e)),
3606 message ("Operand of %s is non-numeric (%t): %s",
3607 lltok_unparse (op), t, exprNode_unparse (e)),
3610 ret->typ = ctype_unknown;
3613 /* if (ctype_isZero (t)) e->typ = ctype_int; */
3615 exprNode_checkModify (e, ret);
3617 /* added 7/11/2000 D.L */
3619 /*DRL 6/8/01 I decided to disable all LCLint Warning here since the code
3620 probably needs a rewrite any way */
3624 // updateEnvironmentForPostOp (e);
3626 /* start modifications */
3627 /* added by Seejo on 4/16/2000 */
3629 /* Arithmetic operations on pointers wil modify the size/len/null terminated
3631 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
3633 ret->sref = sRef_copy (e->sref);
3636 if (lltok_getTok (op) == INC_OP) {
3637 if (sRef_getSize(e->sref) > 0) {
3639 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
3641 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
3642 /* Assumption: there is only 1 \0 in the buffer */
3643 /* This will not be correct if there are 2 \0's in the buffer */
3644 sRef_setNotNullTerminatedState(ret->sref);
3645 sRef_resetLen(ret->sref);
3647 sRef_setNullTerminatedState(ret->sref);
3648 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
3650 if (sRef_isNullTerminated (ret->sref))
3651 printf ("ret->sref is Null Terminated\n");
3652 else if (sRef_isPossiblyNullTerminated (ret->sref))
3653 printf ("ret->sref is Possibly Null Terminated\n");
3654 else if (sRef_isNotNullTerminated (ret->sref))
3655 printf ("ret->sref is Not Null Terminated\n");
3660 if (lltok_getTok (op) == DEC_OP) {
3661 if (sRef_getSize(e->sref) >= 0) {
3662 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
3663 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
3668 /* end modifications */
3674 exprNode_preOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
3676 bool checkMod = FALSE;
3678 int opid = lltok_getTok (op);
3679 exprNode ret = exprNode_createSemiCopy (e);
3681 exprNode_copySets (ret, e);
3683 multiVal_free (ret->val);
3684 ret->val = multiVal_undefined;
3685 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
3686 ret->kind = XPR_PREOP;
3687 ret->edata = exprData_makeUop (e, op);
3689 if (exprNode_isError (e))
3694 checkMacroParen (e);
3696 te = exprNode_getType (e);
3697 tr = ctype_realType (te);
3699 if (opid != TAMPERSAND)
3701 exprNode_checkUse (ret, e->sref, e->loc);
3703 if (ctype_isRealAbstract (tr)
3704 && (!(ctype_isRealBool (te) && (opid == TEXCL))))
3706 if (optgenerror (FLG_ABSTRACT,
3707 message ("Operand of %s is abstract type (%t): %s",
3708 lltok_unparse (op), tr,
3709 exprNode_unparse (ret)),
3712 tr = te = ctype_unknown;
3713 ret->typ = ctype_unknown;
3714 sRef_setNullError (e->sref);
3722 case DEC_OP: /* should also check modification! */
3724 if (sRef_isMacroParamRef (e->sref))
3728 message ("Operand of %s is macro parameter (non-functional): %s",
3729 lltok_unparse (op), exprNode_unparse (ret)),
3734 exprNode_checkSet (ret, e->sref);
3737 if (ctype_isForceRealNumeric (&tr) || ctype_isRealAP (tr))
3742 if (context_msgStrictOps ())
3746 message ("Operand of %s is non-numeric (%t): %s",
3747 lltok_unparse (op), te, exprNode_unparse (ret)),
3750 ret->typ = ctype_int;
3753 /* start modifications */
3754 /* added by Seejo on 4/16/2000 */
3756 /* Arithmetic operations on pointers wil modify the size/len/null terminated
3758 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
3760 ret->sref = sRef_copy (e->sref);
3763 if (lltok_getTok (op) == INC_OP) {
3764 if (sRef_getSize(e->sref) > 0) {
3766 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
3768 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
3769 /* Assumption: there is only 1 \0 in the buffer */
3770 /* This will not be correct if there are 2 \0's in the buffer */
3771 sRef_setNotNullTerminatedState(ret->sref);
3772 sRef_resetLen (ret->sref);
3774 sRef_setNullTerminatedState(ret->sref);
3775 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
3781 if (lltok_getTok (op) == DEC_OP) {
3782 if (sRef_getSize(e->sref) >= 0) {
3783 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
3784 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
3789 /* end modifications */
3796 if (ctype_isForceRealNumeric (&tr))
3800 ret->val = multiVal_invert (exprNode_getValue (e));
3804 ret->val = multiVal_copy (exprNode_getValue (e));
3809 if (context_msgStrictOps ())
3813 message ("Operand of %s is non-numeric (%t): %s",
3814 lltok_unparse (op), te, exprNode_unparse (ret)),
3818 ret->typ = ctype_int;
3822 case TEXCL: /* maybe this should be restricted */
3823 guardSet_flip (ret->guards);
3825 if (ctype_isRealBool (te))
3831 if (ctype_isRealPointer (tr))
3833 if (sRef_isKnown (e->sref))
3835 ret->guards = guardSet_addFalseGuard (ret->guards, e->sref);
3839 (FLG_BOOLOPS, FLG_PTRNEGATE,
3840 message ("Operand of %s is non-boolean (%t): %s",
3841 lltok_unparse (op), te, exprNode_unparse (ret)),
3848 message ("Operand of %s is non-boolean (%t): %s",
3849 lltok_unparse (op), te, exprNode_unparse (ret)),
3853 ret->typ = ctype_bool;
3858 if (ctype_isForceRealInt (&tr))
3863 if (context_msgStrictOps ())
3867 message ("Operand of %s is non-integer (%t): %s",
3868 lltok_unparse (op), te, exprNode_unparse (ret)),
3872 if (ctype_isInt (e->typ))
3878 ret->typ = ctype_int;
3884 ret->typ = ctype_makePointer (e->typ);
3886 if (sRef_isKnown (e->sref))
3888 ret->sref = sRef_makeAddress (e->sref);
3895 if (ctype_isAP (tr))
3897 ret->typ = ctype_baseArrayPtr (e->typ);
3901 if (ctype_isKnown (te))
3903 if (ctype_isFunction (te))
3909 message ("Dereference of function type (%t): %s",
3910 te, exprNode_unparse (ret)),
3915 voptgenerror (FLG_TYPE,
3916 message ("Dereference of non-pointer (%t): %s",
3917 te, exprNode_unparse (ret)),
3919 ret->typ = ctype_unknown;
3924 ret->typ = ctype_unknown;
3929 if (sRef_isKnown (e->sref))
3931 if (sRef_possiblyNull (e->sref))
3933 if (!usymtab_isGuarded (e->sref) && !context_inProtectVars ())
3937 message ("Dereference of %s pointer %q: %s",
3938 sRef_nullMessage (e->sref),
3939 sRef_unparse (e->sref),
3940 exprNode_unparse (ret)),
3943 sRef_showNullInfo (e->sref);
3944 sRef_setNotNull (e->sref, e->loc); /* suppress future messages */
3949 ret->sref = sRef_makePointer (e->sref);
3954 llbug (message ("exprNode_preOp: unhandled op: %s", lltok_unparse (op)));
3959 exprNode_checkModify (e, ret);
3966 ** any reason to disallow sizeof (abstract type) ?
3970 ** used by both sizeof
3974 ctype sizeof_resultType (void)
3976 static ctype sizet = ctype_unknown;
3978 if (ctype_isUnknown (sizet))
3980 if (usymtab_existsType (cstring_makeLiteralTemp ("size_t")))
3982 sizet = uentry_getAbstractType (usymtab_lookup (cstring_makeLiteralTemp ("size_t")));
3986 sizet = ctype_ulint;
3993 exprNode_sizeofType (/*@only@*/ qtype qt)
3995 exprNode ret = exprNode_create (sizeof_resultType ());
3996 ctype ct = qtype_getType (qt);
3998 ret->kind = XPR_SIZEOFT;
3999 ret->edata = exprData_makeSizeofType (qt);
4001 voptgenerror (FLG_SIZEOFTYPE,
4002 message ("Parameter to sizeof is type %s: %s",
4004 exprNode_unparse (ret)),
4011 exprNode_alignofType (/*@only@*/ qtype qt)
4013 exprNode ret = exprNode_create (sizeof_resultType ());
4014 ctype ct = qtype_getType (qt);
4016 ret->kind = XPR_ALIGNOFT;
4017 ret->edata = exprData_makeSizeofType (qt);
4019 voptgenerror (FLG_SIZEOFTYPE,
4020 message ("Parameter to alignof is type %s: %s",
4022 exprNode_unparse (ret)),
4028 exprNode exprNode_offsetof (qtype qt, cstringList s)
4030 exprNode ret = exprNode_create (sizeof_resultType ());
4031 ctype ct = qtype_getType (qt);
4033 ret->kind = XPR_OFFSETOF;
4034 ret->edata = exprData_makeOffsetof (qt, s);
4036 if (!ctype_isRealSU (ct))
4038 voptgenerror (FLG_TYPE,
4039 message ("First parameter to offsetof is not a "
4040 "struct or union type (type %s): %s",
4042 exprNode_unparse (ret)),
4049 cstringList_elements (s, el) {
4053 if (ctype_isUndefined (lt))
4057 else if (!ctype_isRealSU (lt))
4059 voptgenerror (FLG_TYPE,
4060 message ("Inner offsetof type is not a "
4061 "struct or union type (type %s before field %s): %s",
4062 ctype_unparse (lt), el,
4063 exprNode_unparse (ret)),
4069 fields = ctype_getFields (ctype_realType (lt));
4070 fld = uentryList_lookupField (fields, el);
4071 DPRINTF (("Try: %s / %s", ctype_unparse (lt), el));
4073 if (uentry_isUndefined (fld))
4075 if (ctype_equal (lt, ct)) {
4076 voptgenerror (FLG_TYPE,
4077 message ("Field %s in offsetof is not the "
4078 "name of a field of %s: %s",
4081 exprNode_unparse (ret)),
4084 voptgenerror (FLG_TYPE,
4085 message ("Deep field %s in offsetof is not the "
4086 "name of a field of %s: %s",
4089 exprNode_unparse (ret)),
4095 lt = uentry_getType (fld);
4098 } end_cstringList_elements;
4100 /* Should report error if its a bit field - behavior is undefined! */
4107 exprNode_sizeofExpr (/*@only@*/ exprNode e)
4111 if (exprNode_isUndefined (e))
4113 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4114 ret->edata = exprData_makeSingle (e);
4115 ret->typ = sizeof_resultType ();
4116 ret->kind = XPR_SIZEOF;
4120 uentry u = exprNode_getUentry (e);
4122 ret = exprNode_createPartialCopy (e);
4123 ret->edata = exprData_makeSingle (e);
4125 ret->typ = sizeof_resultType ();
4126 ret->kind = XPR_SIZEOF;
4128 if (uentry_isValid (u)
4129 && uentry_isRefParam (u)
4130 && ctype_isRealArray (uentry_getType (u)))
4133 (FLG_SIZEOFFORMALARRAY,
4134 message ("Parameter to sizeof is an array-type function parameter: %s",
4135 exprNode_unparse (ret)),
4141 ** sizeof (x) doesn't "really" use x
4148 exprNode_alignofExpr (/*@only@*/ exprNode e)
4152 if (exprNode_isUndefined (e))
4154 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4158 ret = exprNode_createPartialCopy (e);
4161 ret->edata = exprData_makeSingle (e);
4162 ret->typ = sizeof_resultType ();
4163 ret->kind = XPR_ALIGNOF;
4166 ** sizeof (x) doesn't "really" use x
4173 exprNode_cast (/*@only@*/ lltok tok, /*@only@*/ exprNode e, /*@only@*/ qtype q)
4179 if (exprNode_isError (e))
4182 lltok_release (tok);
4183 return exprNode_undefined;
4186 checkMacroParen (e);
4188 c = qtype_getType (q);
4189 t = exprNode_getType (e);
4191 ret = exprNode_createPartialCopy (e);
4193 ret->loc = fileloc_update (ret->loc, lltok_getLoc (tok));
4195 ret->kind = XPR_CAST;
4196 ret->edata = exprData_makeCast (tok, e, q);
4198 if (ctype_isRealSU (ctype_getBaseType (sRef_getType (e->sref))))
4201 ** This is a bit of a hack to avoid a problem
4202 ** when the code does,
4203 ** (some other struct) x
4208 ret->sref = sRef_copy (e->sref);
4209 usymtab_addForceMustAlias (ret->sref, e->sref);
4210 sRef_setTypeFull (ret->sref, c);
4211 DPRINTF (("Cast: %s -> %s", sRef_unparseFull (e->sref),
4212 sRef_unparseFull (ret->sref)));
4216 ret->sref = e->sref;
4217 sRef_setTypeFull (ret->sref, c);
4218 DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref)));
4225 ** void * <-> abstract * (if FLG_ABSTVOIDP)
4226 ** abstract * <-> void * (if FLG_ABSTVOIDP)
4229 if (ctype_isVoid (c)) /* cast to void is always okay --- discard value */
4233 else if (ctype_isRealAP (c)) /* casting to array or pointer */
4235 ctype bc = ctype_getBaseType (c);
4236 ctype bt = ctype_getBaseType (t);
4237 ctype rt = ctype_realType (t);
4239 if (ctype_isFunction (ctype_baseArrayPtr (ctype_realType (c)))
4240 && (ctype_isArrayPtr (rt)
4241 && !ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
4245 message ("Cast from function pointer type (%t) to "
4246 "non-function pointer (%t): %s",
4247 c, t, exprNode_unparse (ret)),
4251 if (!ctype_isFunction (ctype_baseArrayPtr (c))
4252 && (ctype_isArrayPtr (rt)
4253 && ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
4257 message ("Cast from non-function pointer type (%t) to "
4258 "function pointer (%t): %s",
4259 c, t, exprNode_unparse (ret)),
4263 if (exprNode_isZero (e) && context_getFlag (FLG_ZEROPTR) &&
4264 !(ctype_isRealAbstract (bc)
4265 && context_hasAccess (ctype_typeId (bc))))
4267 ; /* okay to cast zero */
4271 if (ctype_isRealAbstract (bc)
4272 && !context_hasAccess (ctype_typeId (bc)))
4274 if (ctype_isVoidPointer (t) || ctype_isUnknown (t))
4278 message ("Cast to underlying abstract type %t: %s",
4279 c, exprNode_unparse (ret)),
4286 message ("Cast to underlying abstract type %t: %s",
4287 c, exprNode_unparse (ret)),
4292 if (ctype_isRealAbstract (bt)
4293 && !context_hasAccess (ctype_typeId (bt)))
4295 if (ctype_isUnknown (c) || ctype_isVoidPointer (c))
4299 message ("Cast from underlying abstract type %t: %s",
4300 t, exprNode_unparse (ret)),
4307 message ("Cast from underlying abstract type %t: %s",
4308 t, exprNode_unparse (ret)),
4316 ctype bt = ctype_realType (ctype_getBaseType (t));
4317 ctype bc = ctype_realType (ctype_getBaseType (c));
4319 if (ctype_isAbstract (bt) && !context_hasAccess (ctype_typeId (bt)))
4321 if (ctype_match (c, t))
4323 if (ctype_equal (c, t))
4327 message ("Redundant cast involving abstract type %t: %s",
4328 bt, exprNode_unparse (ret)),
4336 message ("Cast from abstract type %t: %s",
4337 bt, exprNode_unparse (ret)),
4342 if (ctype_isAbstract (bc)
4343 && !context_hasAccess (ctype_typeId (bc)))
4345 if (ctype_match (c, t))
4353 message ("Cast to abstract type %t: %s", bc,
4354 exprNode_unparse (ret)),
4360 if (ctype_isAbstract (c))
4362 if (sRef_isExposed (e->sref) || sRef_isOnly (e->sref))
4364 /* okay, cast exposed to abstract */
4365 sRef_clearExKindComplete (ret->sref, fileloc_undefined);
4369 if (ctype_isVisiblySharable (t)
4370 && sRef_isExternallyVisible (e->sref)
4371 && !(ctype_isAbstract (t)
4372 && context_hasAccess (ctype_typeId (t))))
4376 message ("Cast to abstract type from externally visible "
4377 "mutable storage exposes rep of %s: %s",
4379 exprNode_unparse (e)),
4389 evaluationOrderUndefined (lltok op)
4391 int opid = lltok_getTok (op);
4393 return (opid != AND_OP && opid != OR_OP);
4396 static bool checkIntegral (/*@notnull@*/ exprNode e1,
4397 /*@notnull@*/ exprNode e2,
4398 /*@notnull@*/ exprNode ret,
4403 ctype te1 = exprNode_getType (e1);
4404 ctype te2 = exprNode_getType (e2);
4406 ctype tr1 = ctype_realishType (te1);
4407 ctype tr2 = ctype_realishType (te2);
4409 if (ctype_isForceRealInt (&tr1) && ctype_isForceRealInt (&tr2))
4415 if (context_msgStrictOps ())
4417 if (!ctype_isInt (tr1) && !ctype_isInt (tr2))
4419 if (ctype_sameName (te1, te2))
4423 message ("Operands of %s are non-integer (%t): %s",
4424 lltok_unparse (op), te1,
4425 exprNode_unparse (ret)),
4432 message ("Operands of %s are non-integers (%t, %t): %s",
4433 lltok_unparse (op), te1, te2,
4434 exprNode_unparse (ret)),
4438 else if (!ctype_isInt (tr1))
4442 message ("Left operand of %s is non-integer (%t): %s",
4443 lltok_unparse (op), te1, exprNode_unparse (ret)),
4447 /* !ctype_isInt (te2) */
4451 message ("Right operand of %s is non-integer (%t): %s",
4452 lltok_unparse (op), te2, exprNode_unparse (ret)),
4462 ** returns exprNode representing e1 op e2
4464 ** uses msg if there are errors
4465 ** can be used for both assignment ops and regular ops
4470 static /*@only@*/ /*@notnull@*/ exprNode
4471 exprNode_makeOp (/*@keep@*/ exprNode e1, /*@keep@*/ exprNode e2,
4472 /*@keep@*/ lltok op)
4474 ctype te1, te2, tr1, tr2, tret;
4475 int opid = lltok_getTok (op);
4476 bool hasError = FALSE;
4479 if (exprNode_isError (e1))
4481 ret = exprNode_createPartialNVCopy (e2);
4485 ret = exprNode_createPartialNVCopy (e1);
4488 ret->val = multiVal_undefined;
4490 ret->edata = exprData_makeOp (e1, e2, op);
4492 if (exprNode_isError (e1) || exprNode_isError (e2))
4494 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
4495 || opid == EQ_OP || opid == NE_OP
4496 || opid == AND_OP || opid == OR_OP)
4498 ret->typ = ctype_bool;
4501 if (exprNode_isDefined (e1))
4503 exprNode_checkUse (ret, e1->sref, e1->loc);
4506 if (exprNode_isDefined (e2))
4508 exprNode_mergeUSs (ret, e2);
4509 exprNode_checkUse (ret, e2->sref, e2->loc);
4515 tret = ctype_unknown;
4516 te1 = exprNode_getType (e1);
4517 DPRINTF (("te1 = %s / %s", exprNode_unparse (e1), ctype_unparse (te1)));
4519 te2 = exprNode_getType (e2);
4521 tr1 = ctype_realishType (te1);
4522 tr2 = ctype_realishType (te2);
4526 ret->guards = guardSet_or (ret->guards, e2->guards);
4528 else if (opid == AND_OP)
4530 ret->guards = guardSet_and (ret->guards, e2->guards);
4537 if (opid == EQ_OP || opid == NE_OP)
4539 exprNode temp1 = e1, temp2 = e2;
4541 /* could do NULL == x */
4543 if (exprNode_isNullValue (e1) || exprNode_isUnknownConstant (e1))
4545 temp1 = e2; temp2 = e1;
4548 if (exprNode_isNullValue (temp2) || exprNode_isUnknownConstant (temp2))
4550 reflectNullTest (temp1, (opid == NE_OP));
4551 guardSet_free (ret->guards);
4552 ret->guards = guardSet_copy (temp1->guards);
4556 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
4557 || opid == EQ_OP || opid == NE_OP || opid == AND_OP || opid == OR_OP)
4562 if (anyAbstract (tr1, tr2) &&
4563 (!((ctype_isRealBool (te1) || ctype_isRealBool (te2)) &&
4564 (opid == AND_OP || opid == OR_OP
4565 || opid == EQ_OP || opid == NE_OP))))
4567 abstractOpError (tr1, tr2, op, e1, e2, e1->loc, e2->loc);
4569 else if (ctype_isUnknown (te1) || ctype_isUnknown (te2))
4571 /* unknown types, no comparisons possible */
4577 case TMULT: /* multiplication and division: */
4579 case MUL_ASSIGN: /* numeric, numeric -> numeric */
4580 case DIV_ASSIGN: /* */
4582 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
4585 case TPLUS: /* addition and subtraction: */
4586 case TMINUS: /* pointer, int -> pointer */
4587 case SUB_ASSIGN: /* int, pointer -> pointer */
4588 case ADD_ASSIGN: /* numeric, numeric -> numeric */
4590 tr1 = ctype_fixArrayPtr (tr1);
4592 if ((ctype_isRealPointer (tr1) && !exprNode_isNullValue (e1))
4593 && (!ctype_isRealPointer (tr2) && ctype_isRealInt (tr2)))
4597 if (context_msgPointerArith ())
4601 message ("Pointer arithmetic (%t, %t): %s",
4602 te1, te2, exprNode_unparse (ret)),
4606 if (sRef_possiblyNull (e1->sref)
4607 && !usymtab_isGuarded (e1->sref))
4610 (FLG_NULLPOINTERARITH,
4611 message ("Pointer arithmetic involving possibly "
4612 "null pointer %s: %s",
4613 exprNode_unparse (e1),
4614 exprNode_unparse (ret)),
4618 ret->sref = sRef_copy (e1->sref);
4620 /* start modifications */
4621 /* added by Seejo on 4/16/2000 */
4623 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4625 if ((sRef_isPossiblyNullTerminated (e1->sref)) || (sRef_isNullTerminated(e1->sref))) {
4626 //if (sRef_isKnown (e->sref)) {
4627 //ret->sref = sRef_makeAddress (e->sref);
4632 added ugly fixed to stop
4633 program from crashing on point + int +int
4634 one day I'll fix this or ask Seejo wtf the codes supposed to do. */
4636 if (!multiVal_isInt (e2->val) )
4640 val = (int) multiVal_forceInt (e2->val);
4642 /* Operator : + or += */
4643 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
4644 if (sRef_getSize(e1->sref) >= val) {/* Incrementing the pointer by
4645 val should not result in a
4646 size < 0 (size = 0 is ok !) */
4648 sRef_setSize (ret->sref, sRef_getSize(e1->sref) - val);
4650 if (sRef_getLen(e1->sref) == val) { /* i.e. the character at posn val is \0 */
4651 sRef_setNotNullTerminatedState(ret->sref);
4652 sRef_resetLen (ret->sref);
4654 sRef_setNullTerminatedState(ret->sref);
4655 sRef_setLen (ret->sref, sRef_getLen(e1->sref) - val);
4660 /* Operator : - or -= */
4661 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
4662 if (sRef_getSize(e1->sref) >= 0) {
4663 sRef_setSize (ret->sref, sRef_getSize(e1->sref) + val);
4664 sRef_setLen (ret->sref, sRef_getLen(e1->sref) + val);
4669 /* end modifications */
4671 sRef_setNullError (ret->sref);
4674 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
4675 ** since is points to storage that should not be deallocated
4676 ** through this pointer.
4679 if (sRef_isOnly (ret->sref)
4680 || sRef_isFresh (ret->sref))
4682 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
4687 else if ((!ctype_isRealPointer(tr1) && ctype_isRealInt (tr1))
4688 && (ctype_isRealPointer (tr2) && !exprNode_isNullValue (e2)))
4690 if (context_msgPointerArith ())
4694 message ("Pointer arithmetic (%t, %t): %s",
4695 te1, te2, exprNode_unparse (ret)),
4699 if (sRef_possiblyNull (e1->sref)
4700 && !usymtab_isGuarded (e1->sref))
4703 (FLG_NULLPOINTERARITH,
4704 message ("Pointer arithmetic involving possibly "
4705 "null pointer %s: %s",
4706 exprNode_unparse (e2),
4707 exprNode_unparse (ret)),
4711 ret->sref = sRef_copy (e2->sref);
4713 /* start modifications */
4714 /* added by Seejo on 4/16/2000 */
4716 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4719 if ((sRef_isPossiblyNullTerminated (e2->sref)) || (sRef_isNullTerminated(e2->sref))) {
4720 //if (sRef_isKnown (e->sref)) {
4721 //ret->sref = sRef_makeAddress (e->sref);
4724 int val = (int) multiVal_forceInt (e1->val);
4726 /* Operator : + or += */
4727 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
4728 if (sRef_getSize(e2->sref) >= val) {/* Incrementing the pointer by
4729 val should not result in a
4730 size < 0 (size = 0 is ok !) */
4732 sRef_setSize (ret->sref, sRef_getSize(e2->sref) - val);
4734 if (sRef_getLen(e2->sref) == val) { /* i.e. the character at posn val is \0 */
4735 sRef_setNotNullTerminatedState(ret->sref);
4736 sRef_resetLen (ret->sref);
4738 sRef_setNullTerminatedState(ret->sref);
4739 sRef_setLen (ret->sref, sRef_getLen(e2->sref) - val);
4744 /* Operator : - or -= */
4745 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
4746 if (sRef_getSize(e2->sref) >= 0) {
4747 sRef_setSize (ret->sref, sRef_getSize(e2->sref) + val);
4748 sRef_setLen (ret->sref, sRef_getLen(e2->sref) + val);
4753 /* end modifications */
4755 sRef_setNullError (ret->sref);
4758 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
4759 ** since is points to storage that should not be deallocated
4760 ** through this pointer.
4763 if (sRef_isOnly (ret->sref)
4764 || sRef_isFresh (ret->sref)) {
4765 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
4769 ret->sref = e2->sref;
4773 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
4778 case LEFT_ASSIGN: /* Shifts: should be unsigned values */
4782 case TAMPERSAND: /* bitwise & */
4784 case TCIRC: /* ^ (XOR) */
4789 bool reported = FALSE;
4790 flagcode code = FLG_BITWISEOPS;
4792 if (opid == LEFT_OP || opid == LEFT_ASSIGN
4793 || opid == RIGHT_OP || opid == RIGHT_ASSIGN) {
4794 code = FLG_SHIFTSIGNED;
4797 if (!ctype_isUnsigned (tr1))
4799 if (exprNode_isNonNegative (e1)) {
4802 reported = optgenerror
4804 message ("Left operand of %s is not unsigned value (%t): %s",
4805 lltok_unparse (op), te1,
4806 exprNode_unparse (ret)),
4816 /* right need not be signed for shifts */
4817 if (code != FLG_SHIFTSIGNED
4818 && !ctype_isUnsigned (tr2))
4820 if (!exprNode_isNonNegative (e2)) {
4821 reported = optgenerror
4823 message ("Right operand of %s is not unsigned value (%t): %s",
4824 lltok_unparse (op), te2,
4825 exprNode_unparse (ret)),
4833 if (!checkIntegral (e1, e2, ret, op)) {
4834 te1 = ctype_unknown;
4838 DPRINTF (("Set: %s", ctype_unparse (te1)));
4841 ** tret is the widest type of te1 and te2
4844 tret = ctype_widest (te1, te2);
4849 if (checkIntegral (e1, e2, ret, op)) {
4852 tret = ctype_unknown;
4857 case TLT: /* comparisons */
4858 case TGT: /* numeric, numeric -> bool */
4859 if ((ctype_isReal (tr1) && !ctype_isInt (tr1))
4860 || (ctype_isReal (tr2) && !ctype_isInt (tr2)))
4863 bool fepsilon = FALSE;
4865 if (!ctype_isReal (rtype) || ctype_isInt (rtype))
4870 if (opid == TLT || opid == TGT)
4872 uentry ue1 = exprNode_getUentry (e1);
4873 uentry ue2 = exprNode_getUentry (e2);
4876 ** FLT_EPSILON, etc. really is a variable, not
4880 if (uentry_isVariable (ue1))
4882 cstring uname = uentry_rawName (ue1);
4884 if (cstring_equalLit (uname, "FLT_EPSILON")
4885 || cstring_equalLit (uname, "DBL_EPSILON")
4886 || cstring_equalLit (uname, "LDBL_EPSILON"))
4892 if (uentry_isVariable (ue2))
4894 cstring uname = uentry_rawName (ue2);
4896 if (cstring_equalLit (uname, "FLT_EPSILON")
4897 || cstring_equalLit (uname, "DBL_EPSILON")
4898 || cstring_equalLit (uname, "LDBL_EPSILON"))
4907 ; /* Don't complain. */
4913 message ("Dangerous comparison involving %s types: %s",
4914 ctype_unparse (rtype),
4915 exprNode_unparse (ret)),
4924 ** Types should match.
4927 if (!exprNode_matchTypes (e1, e2))
4929 hasError = gentypeerror
4931 message ("Operands of %s have incompatible types (%t, %t): %s",
4932 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
4938 || (ctype_isForceRealNumeric (&tr1)
4939 && ctype_isForceRealNumeric (&tr2)) ||
4940 (ctype_isRealPointer (tr1) && ctype_isRealPointer (tr2)))
4946 if ((ctype_isRealNumeric (tr1) && ctype_isRealPointer (tr2)) ||
4947 (ctype_isRealPointer (tr1) && ctype_isRealNumeric (tr2)))
4951 message ("Comparison of pointer and numeric (%t, %t): %s",
4952 te1, te2, exprNode_unparse (ret)),
4957 (void) checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
4962 /* EQ_OP should NOT be used with booleans (unless one is FALSE) */
4964 if ((opid == EQ_OP || opid == NE_OP) &&
4965 ctype_isDirectBool (tr1) && ctype_isDirectBool (tr2))
4968 ** is one a variable?
4971 if (uentry_isVariable (exprNode_getUentry (e1))
4972 || uentry_isVariable (exprNode_getUentry (e2)))
4975 ** comparisons with FALSE are okay
4978 if (exprNode_isFalseConstant (e1)
4979 || exprNode_isFalseConstant (e2))
4988 ("Use of %q with %s variables (risks inconsistency because "
4989 "of multiple true values): %s",
4990 cstring_makeLiteral ((opid == EQ_OP) ? "==" : "!="),
4991 context_printBoolName (), exprNode_unparse (ret)),
4998 case AND_OP: /* bool, bool -> bool */
5001 if (ctype_isForceRealBool (&tr1) && ctype_isForceRealBool (&tr2))
5007 if (context_maybeSet (FLG_BOOLOPS))
5009 if (!ctype_isRealBool (te1) && !ctype_isRealBool (te2))
5011 if (ctype_sameName (te1, te2))
5015 message ("Operands of %s are non-boolean (%t): %s",
5016 lltok_unparse (op), te1,
5017 exprNode_unparse (ret)),
5025 ("Operands of %s are non-booleans (%t, %t): %s",
5026 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5030 else if (!ctype_isRealBool (te1))
5034 message ("Left operand of %s is non-boolean (%t): %s",
5035 lltok_unparse (op), te1, exprNode_unparse (ret)),
5038 else if (!ctype_isRealBool (te2))
5042 message ("Right operand of %s is non-boolean (%t): %s",
5043 lltok_unparse (op), te2, exprNode_unparse (ret)),
5056 (cstring_makeLiteral
5057 ("There has been a problem in the parser. This is due to a bug "
5058 "in either lclint, bison or gcc version 2.95 optimizations, "
5059 "but it has not been confirmed. Please try rebuidling LCLint "
5060 "without the -O<n> option."));
5065 DPRINTF (("Return type: %s", ctype_unparse (tret)));
5068 exprNode_checkUse (ret, e1->sref, e1->loc);
5069 exprNode_mergeUSs (ret, e2);
5070 exprNode_checkUse (ret, e2->sref, e2->loc);
5076 exprNode_op (/*@only@*/ exprNode e1, /*@keep@*/ exprNode e2,
5077 /*@only@*/ lltok op)
5081 checkMacroParen (e1);
5082 checkMacroParen (e2);
5084 if (evaluationOrderUndefined (op) && context_maybeSet (FLG_EVALORDER))
5086 checkExpressionDefined (e1, e2, op);
5089 ret = exprNode_makeOp (e1, e2, op);
5094 void exprNode_checkAssignMod (exprNode e1, exprNode ret)
5097 ** This is somewhat bogus!
5099 ** Assigning to a nested observer in a non-observer datatype
5100 ** should not produce an error.
5103 sRef ref = exprNode_getSref (e1);
5105 DPRINTF (("Check assign mod: %s",
5106 sRef_unparseFull (ref)));
5108 if (sRef_isObserver (ref)
5109 || ((sRef_isFileStatic (ref) || sRef_isGlobal (ref))
5110 && ctype_isArray (ctype_realType (sRef_getType (ref)))))
5112 sRef base = sRef_getBase (ref);
5114 if (sRef_isValid (base) && sRef_isObserver (base))
5116 exprNode_checkModify (e1, ret);
5120 exprNode_checkModifyVal (e1, ret);
5125 exprNode_checkModify (e1, ret);
5130 exprNode_assign (/*@only@*/ exprNode e1,
5131 /*@only@*/ exprNode e2, /*@only@*/ lltok op)
5133 bool isalloc = FALSE;
5134 bool isjustalloc = FALSE;
5137 DPRINTF (("%s [%s] <- %s [%s]",
5138 exprNode_unparse (e1),
5139 ctype_unparse (e1->typ),
5140 exprNode_unparse (e2),
5141 ctype_unparse (e2->typ)));
5143 if (lltok_getTok (op) != TASSIGN)
5145 ret = exprNode_makeOp (e1, e2, op);
5149 ret = exprNode_createPartialCopy (e1);
5150 ret->kind = XPR_ASSIGN;
5151 ret->edata = exprData_makeOp (e1, e2, op);
5153 if (!exprNode_isError (e2))
5155 ret->sets = sRefSet_union (ret->sets, e2->sets);
5156 ret->msets = sRefSet_union (ret->msets, e2->msets);
5157 ret->uses = sRefSet_union (ret->uses, e2->uses);
5161 checkExpressionDefined (e1, e2, op);
5163 if (exprNode_isError (e1))
5165 if (!exprNode_isError (e2))
5167 ret->loc = fileloc_update (ret->loc, e2->loc);
5171 ret->loc = fileloc_update (ret->loc, g_currentloc);
5175 if (!exprNode_isError (e2))
5177 checkMacroParen (e2);
5180 if (exprNode_isDefined (e1))
5182 if (sRef_isMacroParamRef (e1->sref))
5184 if (context_inIterDef ())
5186 uentry ue = sRef_getUentry (e1->sref);
5188 if (uentry_isYield (ue))
5194 if (fileloc_isDefined (e1->loc))
5198 message ("Assignment to non-yield iter parameter: %q",
5199 sRef_unparse (e1->sref)),
5206 message ("Assignment to non-yield iter parameter: %q",
5207 sRef_unparse (e1->sref)),
5214 if (fileloc_isDefined (e1->loc))
5218 message ("Assignment to macro parameter: %q",
5219 sRef_unparse (e1->sref)),
5226 message ("Assignment to macro parameter: %q",
5227 sRef_unparse (e1->sref)),
5234 exprNode_checkAssignMod (e1, ret);
5237 if (exprNode_isDefined (e2))
5239 if (lltok_getTok (op) == TASSIGN)
5241 ctype te1 = exprNode_getType (e1);
5242 ctype te2 = exprNode_getType (e2);
5244 if (!ctype_forceMatch (te1, te2))
5246 if (exprNode_matchLiteral (te1, e2))
5254 message ("Assignment of %t to %t: %s %s %s",
5255 te2, te1, exprNode_unparse (e1),
5257 exprNode_unparse (e2)),
5263 exprNode_mergeUSs (ret, e2);
5264 exprNode_checkUse (ret, e2->sref, e2->loc);
5266 doAssign (e1, e2, FALSE);
5267 ret->sref = e1->sref;
5271 if (exprNode_isDefined (e2))
5273 exprNode_mergeUSs (ret, e2);
5274 exprNode_checkUse (ret, e2->sref, e2->loc);
5278 if (sRef_isPointer (e1->sref) && !sRef_isMacroParamRef (e1->sref))
5280 exprNode_checkUse (ret, sRef_getBase (e1->sref), e1->loc);
5283 isjustalloc = sRef_isJustAllocated (e1->sref);
5284 isalloc = sRef_isAllocated (e1->sref);
5286 if (sRef_isField (e1->sref))
5288 sRef root = sRef_getRootBase (sRef_getBase (e1->sref));
5290 if (!sRef_isAllocated (root) && !sRef_isMacroParamRef (root))
5292 exprNode_checkUse (ret, root, e1->loc);
5298 ** be careful! this defines e1->sref.
5301 if (!sRef_isMacroParamRef (e1->sref))
5303 exprNode_checkSet (ret, e1->sref);
5308 sRef_setAllocatedComplete (e1->sref, exprNode_isDefined (e2)
5309 ? e2->loc : e1->loc);
5315 sRef_setAllocatedShallowComplete (e1->sref, exprNode_loc (e2));
5324 exprNode_cond (/*@keep@*/ exprNode pred, /*@keep@*/ exprNode ifclause,
5325 /*@keep@*/ exprNode elseclause)
5329 if (!exprNode_isError (pred))
5331 ret = exprNode_createPartialCopy (pred);
5332 checkMacroParen (pred);
5333 exprNode_checkPred (cstring_makeLiteralTemp ("conditional"), pred);
5335 if (!exprNode_isError (ifclause))
5337 checkMacroParen (ifclause); /* update macro counts! */
5339 if (!exprNode_isError (elseclause))
5341 checkMacroParen (elseclause);
5343 if (!exprNode_matchTypes (ifclause, elseclause))
5346 (exprNode_getType (ifclause),
5348 exprNode_getType (elseclause),
5350 message ("Conditional clauses are not of same type: "
5352 exprNode_unparse (ifclause),
5353 exprNode_getType (ifclause),
5354 exprNode_unparse (elseclause),
5355 exprNode_getType (elseclause)),
5358 ret->sref = sRef_undefined;
5359 ret->typ = ctype_unknown;
5364 /* for now...should merge the states */
5365 ret->sref = ifclause->sref;
5366 ret->typ = ifclause->typ;
5368 if (exprNode_isNullValue (ifclause))
5370 ret->typ = elseclause->typ;
5374 exprNode_checkUse (ret, pred->sref, pred->loc);
5375 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
5376 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
5378 exprNode_mergeCondUSs (ret, ifclause, elseclause);
5383 ret->typ = ifclause->typ;
5385 exprNode_checkUse (pred, pred->sref, pred->loc);
5386 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
5388 exprNode_mergeCondUSs (ret, ifclause, exprNode_undefined);
5393 if (!exprNode_isError (elseclause))
5395 ret->typ = elseclause->typ;
5397 exprNode_checkUse (pred, pred->sref, pred->loc);
5398 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
5400 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
5404 else /* pred is error */
5406 if (!exprNode_isError (ifclause))
5408 ret = exprNode_createSemiCopy (ifclause);
5410 checkMacroParen (ifclause); /* update macro counts! */
5412 if (!exprNode_isError (elseclause))
5414 checkMacroParen (elseclause);
5416 ret->typ = ifclause->typ;
5418 if (!ctype_forceMatch (ifclause->typ, elseclause->typ))
5421 (exprNode_getType (ifclause),
5423 exprNode_getType (elseclause),
5425 message ("Conditional clauses are not of same type: "
5427 exprNode_unparse (ifclause),
5428 exprNode_getType (ifclause),
5429 exprNode_unparse (elseclause),
5430 exprNode_getType (elseclause)),
5433 ret->typ = ctype_unknown;
5437 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
5438 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
5440 exprNode_mergeCondUSs (ret, ifclause, elseclause);
5443 else if (!exprNode_isError (elseclause)) /* pred, if errors */
5445 ret = exprNode_createSemiCopy (ifclause);
5447 ret->typ = elseclause->typ;
5448 checkMacroParen (elseclause);
5450 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
5451 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
5453 else /* all errors! */
5455 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
5459 ret->kind = XPR_COND;
5460 ret->edata = exprData_makeCond (pred, ifclause, elseclause);
5462 if (exprNode_isDefined (ifclause) && exprNode_isDefined (elseclause))
5464 exprNode_combineControl (ret, ifclause, elseclause);
5471 exprNode_vaArg (/*@only@*/ lltok tok, /*@only@*/ exprNode arg, /*@only@*/ qtype qt)
5473 ctype totype = qtype_getType (qt);
5475 exprNode_createPartialLocCopy (arg, fileloc_copy (lltok_getLoc (tok)));
5479 ** check use of va_arg : <valist>, type -> type
5482 if (exprNode_isError (arg))
5487 targ = exprNode_getType (arg);
5490 ** arg should have be a pointer
5493 if (!ctype_isUA (targ) ||
5494 (!usymId_equal (ctype_typeId (targ),
5495 usymtab_getTypeId (cstring_makeLiteralTemp ("va_list")))))
5499 message ("First argument to va_arg is not a va_list (type %t): %s",
5500 targ, exprNode_unparse (arg)),
5504 exprNode_checkSet (ret, arg->sref);
5508 ** return type is totype
5512 ret->kind = XPR_VAARG;
5513 ret->edata = exprData_makeCast (tok, arg, qt);
5518 exprNode exprNode_labelMarker (/*@only@*/ cstring label)
5520 exprNode ret = exprNode_createPlain (ctype_undefined);
5521 ret->kind = XPR_LABEL;
5522 ret->edata = exprData_makeLiteral (label);
5523 ret->isJumpPoint = TRUE;
5525 return (ret); /* for now, ignore label */
5528 exprNode exprNode_notReached (/*@returned@*/ exprNode stmt)
5530 if (exprNode_isDefined (stmt))
5532 stmt->isJumpPoint = TRUE;
5534 /* This prevent stray no return path errors, etc. */
5535 stmt->exitCode = XK_MUSTEXIT;
5541 bool exprNode_isDefaultMarker (exprNode e)
5543 if (exprNode_isDefined (e))
5545 return (e->kind == XPR_DEFAULT || e->kind == XPR_FTDEFAULT);
5551 bool exprNode_isCaseMarker (exprNode e)
5553 if (exprNode_isDefined (e))
5555 return (e->kind == XPR_FTCASE || e->kind == XPR_CASE);
5561 bool exprNode_isLabelMarker (exprNode e)
5563 if (exprNode_isDefined (e))
5565 return (e->kind == XPR_LABEL);
5571 exprNode exprNode_caseMarker (/*@only@*/ exprNode test, bool fallThrough)
5573 exprNode ret = exprNode_createPartialCopy (test);
5575 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
5577 if (exprNode_isError (test)) {
5581 exprNode_checkUse (ret, test->sref, test->loc);
5583 usymtab_setExitCode (ret->exitCode);
5587 usymtab_setMustBreak ();
5590 ret->edata = exprData_makeSingle (test);
5591 ret->isJumpPoint = TRUE;
5597 exprNode exprNode_caseStatement (/*@only@*/ exprNode test, /*@only@*/ exprNode stmt, bool fallThrough)
5599 exprNode ret = exprNode_createPartialCopy (test);
5601 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
5602 ret->edata = exprData_makePair (test, stmt);
5603 ret->isJumpPoint = TRUE;
5605 if (exprNode_isError (test))
5610 exprNode_checkUse (ret, test->sref, test->loc);
5612 if (exprNode_isError (stmt))
5617 exprNode_mergeUSs (ret, stmt);
5619 ret->exitCode = stmt->exitCode;
5620 ret->mustBreak = stmt->mustBreak;
5621 ret->canBreak = stmt->canBreak;
5623 usymtab_setExitCode (ret->exitCode);
5627 usymtab_setMustBreak ();
5634 /*@notnull@*/ /*@only@*/ exprNode
5635 exprNode_defaultMarker (/*@only@*/ lltok def, bool fallThrough)
5637 exprNode ret = exprNode_createTok (def);
5639 ret->isJumpPoint = TRUE;
5640 ret->kind = fallThrough ? XPR_FTDEFAULT : XPR_DEFAULT;
5645 exprNode_mayEscape (exprNode e)
5647 if (exprNode_isDefined (e))
5649 return exitkind_couldEscape (e->exitCode);
5655 exprNode_mustBreak (exprNode e)
5657 if (exprNode_isDefined (e))
5659 return e->mustBreak;
5665 exprNode_mustEscape (exprNode e)
5667 if (exprNode_isDefined (e))
5669 return exitkind_mustEscape (e->exitCode) || exprNode_mustBreak (e);
5676 exprNode_errorEscape (exprNode e)
5678 if (exprNode_isDefined (e))
5680 return exitkind_isError (e->exitCode);
5686 exprNode exprNode_concat (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
5688 exprNode ret = exprNode_createPartialCopy (e1);
5690 ret->edata = exprData_makePair (e1, e2);
5691 ret->kind = XPR_STMTLIST;
5693 if (exprNode_isDefined (e1))
5695 ret->isJumpPoint = e1->isJumpPoint;
5696 ret->canBreak = e1->canBreak;
5700 if (exprNode_isDefined (e2))
5702 ret->loc = fileloc_update (ret->loc, e2->loc);
5706 if (exprNode_isDefined (e2))
5708 ret->exitCode = e2->exitCode;
5709 ret->mustBreak = e2->mustBreak;
5710 if (e2->canBreak) ret->canBreak = TRUE;
5714 ** if e1 must return, then e2 is unreachable!
5717 if (exprNode_isDefined (e1) && exprNode_isDefined (e2))
5719 if ((exprNode_mustEscape (e1) || exprNode_mustBreak (e1))
5720 && !(e2->isJumpPoint))
5722 if (context_getFlag (FLG_UNREACHABLE))
5726 if (e2->kind == XPR_STMT)
5728 nr = exprData_getUopNode (e2->edata);
5731 if ((nr->kind == XPR_TOK
5732 && lltok_isSemi (exprData_getTok (nr->edata))))
5734 /* okay to have unreachable ";" */
5735 ret->exitCode = XK_MUSTEXIT;
5736 ret->canBreak = TRUE;
5740 if (optgenerror (FLG_UNREACHABLE,
5741 message ("Unreachable code: %s",
5742 exprNode_unparseFirst (nr)),
5745 ret->isJumpPoint = TRUE;
5746 ret->mustBreak = FALSE;
5747 ret->exitCode = XK_ERROR;
5748 DPRINTF (("Jump point: %s", exprNode_unparse (ret)));
5752 ret->exitCode = XK_MUSTEXIT;
5753 ret->canBreak = TRUE;
5761 if ((e2->kind == XPR_CASE || e2->kind == XPR_DEFAULT))
5764 ** We want a warning anytime we have:
5766 ** yyy; <<<- no break or return
5770 exprNode lastStmt = exprNode_lastStatement (e1);
5772 if (exprNode_isDefined (lastStmt)
5773 && !exprNode_mustEscape (lastStmt)
5774 && !exprNode_mustBreak (lastStmt)
5775 && !exprNode_isCaseMarker (lastStmt)
5776 && !exprNode_isDefaultMarker (lastStmt)
5777 && !exprNode_isLabelMarker (lastStmt))
5779 voptgenerror (FLG_CASEBREAK,
5781 ("Fall through case (no preceeding break)"),
5788 exprNode_mergeUSs (ret, e2);
5789 // ret = exprNode_mergeEnvironments (ret, e1, e2);
5790 usymtab_setExitCode (ret->exitCode);
5794 usymtab_setMustBreak ();
5800 exprNode exprNode_createTok (/*@only@*/ lltok t)
5802 exprNode ret = exprNode_create (ctype_unknown);
5803 ret->kind = XPR_TOK;
5804 ret->edata = exprData_makeTok (t);
5808 exprNode exprNode_statement (/*@only@*/ exprNode e, /*@only@*/ lltok t)
5810 if (!exprNode_isError (e))
5812 exprNode_checkStatement(e);
5815 return (exprNode_statementError (e, t));
5818 static exprNode exprNode_statementError (/*@only@*/ exprNode e, /*@only@*/ lltok t)
5820 exprNode ret = exprNode_createPartialCopy (e);
5822 if (!exprNode_isError (e))
5824 if (e->kind != XPR_ASSIGN)
5826 exprNode_checkUse (ret, e->sref, e->loc);
5829 ret->exitCode = e->exitCode;
5830 ret->canBreak = e->canBreak;
5831 ret->mustBreak = e->mustBreak;
5834 ret->edata = exprData_makeUop (e, t);
5835 ret->kind = XPR_STMT;
5840 exprNode exprNode_checkExpr (/*@returned@*/ exprNode e)
5842 if (!exprNode_isError (e))
5844 if (e->kind != XPR_ASSIGN)
5846 exprNode_checkUse (e, e->sref, e->loc);
5853 void exprNode_produceGuards (exprNode pred)
5855 if (!exprNode_isError (pred))
5857 if (ctype_isRealPointer (pred->typ))
5859 pred->guards = guardSet_addTrueGuard (pred->guards, pred->sref);
5862 exprNode_checkUse (pred, pred->sref, pred->loc);
5863 exprNode_resetSref (pred);
5867 exprNode exprNode_makeBlock (/*@only@*/ exprNode e)
5869 exprNode ret = exprNode_createPartialCopy (e);
5871 if (!exprNode_isError (e))
5873 ret->exitCode = e->exitCode;
5874 ret->canBreak = e->canBreak;
5875 ret->mustBreak = e->mustBreak;
5878 ret->edata = exprData_makeSingle (e);
5879 ret->kind = XPR_BLOCK;
5883 bool exprNode_isBlock (exprNode e)
5885 return (exprNode_isDefined (e)
5886 && ((e)->kind == XPR_BLOCK));
5889 bool exprNode_isAssign (exprNode e)
5891 if (exprNode_isDefined (e))
5893 return (e->kind == XPR_ASSIGN);
5899 bool exprNode_isEmptyStatement (exprNode e)
5901 return (exprNode_isDefined (e)
5902 && (e->kind == XPR_TOK)
5903 && (lltok_isSemi (exprData_getTok (e->edata))));
5906 exprNode exprNode_if (/*@only@*/ exprNode pred, /*@only@*/ exprNode tclause)
5909 bool emptyErr = FALSE;
5911 if (context_maybeSet (FLG_IFEMPTY))
5913 if (exprNode_isEmptyStatement (tclause))
5915 emptyErr = optgenerror (FLG_IFEMPTY,
5917 ("Body of if statement is empty"),
5918 exprNode_loc (tclause));
5922 if (!emptyErr && context_maybeSet (FLG_IFBLOCK))
5924 if (exprNode_isDefined (tclause)
5925 && !exprNode_isBlock (tclause))
5927 voptgenerror (FLG_IFBLOCK,
5929 ("Body of if statement is not a block: %s",
5930 exprNode_unparse (tclause)),
5931 exprNode_loc (tclause));
5935 if (exprNode_isError (pred))
5937 if (exprNode_isError (tclause))
5939 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
5943 ret = exprNode_createPartialCopy (tclause);
5948 if (exprNode_mustEscape (pred))
5952 message ("Predicate always exits: %s", exprNode_unparse (pred)),
5953 exprNode_loc (pred));
5956 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
5957 exprNode_checkUse (pred, pred->sref, pred->loc);
5959 if (!exprNode_isError (tclause))
5961 exprNode_mergeCondUSs (pred, tclause, exprNode_undefined);
5964 ret = exprNode_createPartialCopy (pred);
5968 ret->edata = exprData_makePair (pred, tclause);
5970 ret->exitCode = XK_UNKNOWN;
5972 if (exprNode_isDefined (tclause))
5974 ret->exitCode = exitkind_makeConditional (tclause->exitCode);
5975 ret->canBreak = tclause->canBreak;
5976 ret->sets = sRefSet_union (ret->sets, tclause->sets);
5977 ret->msets = sRefSet_union (ret->msets, tclause->msets);
5978 ret->uses = sRefSet_union (ret->uses, tclause->uses);
5981 ret->mustBreak = FALSE;
5986 exprNode exprNode_ifelse (/*@only@*/ exprNode pred,
5987 /*@only@*/ exprNode tclause,
5988 /*@only@*/ exprNode eclause)
5991 bool tEmptyErr = FALSE;
5992 bool eEmptyErr = FALSE;
5994 if (context_maybeSet (FLG_IFEMPTY))
5996 if (exprNode_isEmptyStatement (tclause))
5998 tEmptyErr = optgenerror
6001 ("Body of if clause of if statement is empty"),
6002 exprNode_loc (tclause));
6005 if (exprNode_isEmptyStatement (eclause))
6007 eEmptyErr = optgenerror
6010 ("Body of else clause of if statement is empty"),
6011 exprNode_loc (eclause));
6015 if (context_maybeSet (FLG_IFBLOCK))
6018 && exprNode_isDefined (tclause)
6019 && !exprNode_isBlock (tclause))
6021 voptgenerror (FLG_IFBLOCK,
6023 ("Body of if clause of if statement is not a block: %s",
6024 exprNode_unparse (tclause)),
6025 exprNode_loc (tclause));
6029 && exprNode_isDefined (eclause)
6030 && !exprNode_isBlock (eclause)
6031 && !(eclause->kind == XPR_IF)
6032 && !(eclause->kind == XPR_IFELSE))
6037 ("Body of else clause of if statement is not a block: %s",
6038 exprNode_unparse (eclause)),
6039 exprNode_loc (eclause));
6043 if (context_maybeSet (FLG_ELSEIFCOMPLETE))
6045 if (exprNode_isDefined (eclause)
6046 && (eclause->kind == XPR_IF))
6048 voptgenerror (FLG_ELSEIFCOMPLETE,
6049 message ("Incomplete else if logic (no final else): %s",
6050 exprNode_unparse (eclause)),
6051 exprNode_loc (eclause));
6055 if (exprNode_isError (pred))
6057 if (exprNode_isError (tclause))
6059 if (exprNode_isError (eclause))
6061 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
6065 ret = exprNode_createPartialCopy (eclause);
6070 ret = exprNode_createPartialCopy (tclause);
6073 else /* pred is okay */
6075 ret = exprNode_createPartialCopy (pred);
6077 if (exprNode_mustEscape (pred))
6081 message ("Predicate always exits: %s", exprNode_unparse (pred)),
6082 exprNode_loc (pred));
6085 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
6086 exprNode_checkUse (ret, pred->sref, pred->loc);
6088 exprNode_mergeCondUSs (ret, tclause, eclause);
6091 ret->kind = XPR_IFELSE;
6092 ret->edata = exprData_makeCond (pred, tclause, eclause);
6094 if (exprNode_isDefined (tclause) && exprNode_isDefined (eclause))
6096 exprNode_combineControl (ret, tclause, eclause);
6097 ret->loc = fileloc_update (ret->loc, eclause->loc);
6104 ** *allpaths <- TRUE iff all executions paths must go through the switch
6108 checkSwitchExpr (exprNode test, /*@dependent@*/ exprNode e, /*@out@*/ bool *allpaths)
6110 exprNodeSList el = exprNode_flatten (e);
6111 bool mustReturn = TRUE; /* find a branch that doesn't */
6112 bool thisReturn = FALSE;
6113 bool hasDefault = FALSE;
6114 bool hasAllMembers = FALSE;
6115 bool inSwitch = FALSE;
6116 bool isEnumSwitch = FALSE;
6117 bool canBreak = FALSE;
6118 bool fallThrough = FALSE;
6119 ctype ct = ctype_unknown;
6120 enumNameSList usedEnums;
6123 if (exprNode_isDefined (test))
6128 ttype = ctype_realType (ct);
6130 if (ctype_isEnum (ttype))
6132 isEnumSwitch = TRUE;
6133 enums = ctype_elist (ttype);
6134 usedEnums = enumNameSList_new ();
6138 exprNodeSList_elements (el, current)
6140 if (exprNode_isDefined (current))
6142 switch (current->kind)
6150 message ("Duplicate default cases in switch"),
6151 exprNode_loc (current));
6156 if (current->kind == XPR_DEFAULT || current->kind == XPR_FTDEFAULT)
6164 exprNode st = exprData_getSingle (current->edata);
6165 uentry ue = exprNode_getUentry (st);
6167 if (uentry_isValid (ue))
6169 cstring cname = uentry_rawName (ue);
6171 if (enumNameList_member (/*@-usedef@*/enums/*@=usedef@*/, cname))
6173 if (enumNameSList_member
6174 (/*@-usedef@*/usedEnums/*@=usedef@*/, cname))
6178 message ("Duplicate case in switch: %s",
6184 enumNameSList_addh (usedEnums, cname);
6191 message ("Case in switch not %s member: %s",
6192 ctype_unparse (ct), cname),
6199 if (inSwitch && !fallThrough)
6201 if (!thisReturn || canBreak)
6211 /*@switchbreak@*/ break;
6213 thisReturn = thisReturn || exprNode_mustEscape (current);
6214 canBreak = canBreak || current->canBreak;
6215 if (canBreak) fallThrough = FALSE;
6218 } end_exprNodeSList_elements;
6220 if (inSwitch) /* check the last one! */
6222 if (!thisReturn || canBreak)
6231 && (enumNameSList_size (/*@-usedef@*/usedEnums/*@=usedef@*/) !=
6232 enumNameList_size (/*@-usedef@*/enums/*@=usedef@*/)))
6234 enumNameSList unused = enumNameSList_subtract (enums, usedEnums);
6236 voptgenerror (FLG_MISSCASE,
6237 message ("Missing case%s in switch: %q",
6238 cstring_makeLiteralTemp
6239 ((enumNameSList_size (unused) > 1) ? "s" : ""),
6240 enumNameSList_unparse (unused)),
6243 enumNameSList_free (unused);
6247 hasAllMembers = TRUE;
6251 enumNameSList_free (usedEnums);
6255 *allpaths = hasDefault;
6258 exprNodeSList_free (el);
6259 return ((hasDefault || hasAllMembers) && mustReturn);
6262 exprNode exprNode_switch (/*@only@*/ exprNode e, /*@only@*/ exprNode s)
6264 exprNode ret = exprNode_createPartialCopy (e);
6267 DPRINTF (("Switch: %s", exprNode_unparse (s)));
6269 ret->kind = XPR_SWITCH;
6270 ret->edata = exprData_makePair (e, s);
6272 if (!exprNode_isError (s))
6274 exprNode fs = exprNode_firstStatement (s);
6275 ret->loc = fileloc_update (ret->loc, s->loc);
6277 if (exprNode_isUndefined (fs)
6278 || exprNode_isCaseMarker (fs) || exprNode_isLabelMarker (fs)
6279 || exprNode_isDefaultMarker (fs)) {
6282 voptgenerror (FLG_FIRSTCASE,
6284 ("Statement after switch is not a case: %s", exprNode_unparse (fs)),
6289 if (!exprNode_isError (e))
6291 if (checkSwitchExpr (e, s, &allpaths))
6293 ret->exitCode = XK_MUSTRETURN;
6297 ret->exitCode = e->exitCode;
6300 ret->canBreak = e->canBreak;
6301 ret->mustBreak = e->mustBreak;
6305 ** exprNode.c:3883,32: Variable allpaths used before definition
6312 DPRINTF (("Context exit switch!"));
6313 context_exitSwitch (ret, allpaths);
6314 DPRINTF (("Context exit switch done!"));
6319 static void checkInfiniteLoop (/*@notnull@*/ exprNode test,
6320 /*@notnull@*/ exprNode body)
6322 sRefSet tuses = test->uses;
6324 if (!sRefSet_isEmpty (test->uses))
6326 sRefSet sets = sRefSet_newCopy (body->sets);
6327 bool hasError = TRUE;
6328 bool innerState = FALSE;
6329 sRefSet tuncon = sRefSet_undefined;
6331 sets = sRefSet_union (sets, test->sets);
6332 sets = sRefSet_union (sets, body->msets);
6333 sets = sRefSet_union (sets, test->msets);
6335 sRefSet_allElements (tuses, el)
6337 if (sRef_isUnconstrained (el))
6339 tuncon = sRefSet_insert (tuncon, el);
6343 if (sRefSet_member (sets, el))
6350 if (sRef_isInternalState (el)
6351 || sRef_isFileStatic (sRef_getRootBase (el)))
6355 } end_sRefSet_allElements ;
6359 sRefSet suncon = sRefSet_undefined;
6360 bool sinner = FALSE;
6362 sRefSet_allElements (sets, el)
6364 if (sRef_isUnconstrained (el))
6366 suncon = sRefSet_insert (suncon, el);
6368 else if (sRef_isInternalState (el))
6376 } end_sRefSet_allElements ;
6378 if (sinner && innerState)
6382 else if (sRefSet_isEmpty (tuncon)
6383 && sRefSet_isEmpty (suncon))
6388 ("Suspected infinite loop. No value used in loop test (%q) "
6389 "is modified by test or loop body.",
6390 sRefSet_unparsePlain (tuses)),
6395 if (sRefSet_isEmpty (tuncon))
6399 message ("Suspected infinite loop. No condition values "
6400 "modified. Modification possible through "
6401 "unconstrained calls: %q",
6402 sRefSet_unparsePlain (suncon)),
6409 message ("Suspected infinite loop. No condition values "
6410 "modified. Possible undetected dependency through "
6411 "unconstrained calls in loop test: %q",
6412 sRefSet_unparsePlain (tuncon)),
6418 sRefSet_free (sets);
6422 exprNode exprNode_while (/*@keep@*/ exprNode t, /*@keep@*/ exprNode b)
6425 bool emptyErr = FALSE;
6427 if (context_maybeSet (FLG_WHILEEMPTY))
6429 if (exprNode_isEmptyStatement (b))
6431 emptyErr = optgenerror
6434 ("Body of while statement is empty"),
6439 if (!emptyErr && context_maybeSet (FLG_WHILEBLOCK))
6441 if (exprNode_isDefined (b)
6442 && !exprNode_isBlock (b))
6444 if (context_inIterDef ()
6445 && (b->kind == XPR_STMTLIST
6446 || b->kind == XPR_TOK))
6452 voptgenerror (FLG_WHILEBLOCK,
6454 ("Body of while statement is not a block: %s",
6455 exprNode_unparse (b)),
6461 if (exprNode_isError (t))
6463 if (exprNode_isError (b))
6465 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
6469 ret = exprNode_createPartialCopy (b);
6476 ret = exprNode_createPartialCopy (t);
6478 llassert (t->kind == XPR_WHILEPRED);
6480 test = exprData_getSingle (t->edata);
6482 if (!exprNode_isError (b) && exprNode_isDefined (test))
6484 if (context_maybeSet (FLG_INFLOOPS)
6485 || context_maybeSet (FLG_INFLOOPSUNCON))
6488 ** check that some variable in the predicate is set by the body
6489 ** if the predicate uses any variables
6492 checkInfiniteLoop (test, b);
6495 exprNode_mergeUSs (ret, b);
6497 if (exprNode_isDefined (b))
6499 ret->exitCode = exitkind_makeConditional (b->exitCode);
6504 ret->edata = exprData_makePair (t, b);
6505 ret->kind = XPR_WHILE;
6507 if (exprNode_isDefined (t) && exprNode_mustEscape (t))
6511 message ("Predicate always exits: %s", exprNode_unparse (t)),
6515 ret->exitCode = XK_NEVERESCAPE;
6518 ** If loop is infinite, and there is no break inside,
6519 ** exit code is never reach.
6522 if (exprNode_knownIntValue (t))
6524 if (!exprNode_isZero (t))
6526 if (exprNode_isDefined (b))
6530 /* Really, it means never reached. */
6531 ret->exitCode = XK_MUSTEXIT;
6541 ret->canBreak = FALSE;
6542 ret->mustBreak = FALSE;
6548 ** do { b } while (t);
6550 ** note: body passed as first argument
6553 exprNode exprNode_doWhile (/*@only@*/ exprNode b, /*@only@*/ exprNode t)
6557 if (exprNode_isError (t))
6559 if (exprNode_isError (b))
6561 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
6565 ret = exprNode_createPartialCopy (b);
6567 ret->exitCode = exitkind_makeConditional (b->exitCode);
6568 exprNode_checkUse (ret, b->sref, b->loc);
6569 ret->exitCode = b->exitCode;
6570 ret->canBreak = b->canBreak;
6571 ret->mustBreak = b->mustBreak;
6576 ret = exprNode_createPartialCopy (t);
6577 exprNode_checkPred (cstring_makeLiteralTemp ("while"), t);
6579 if (!exprNode_isError (b))
6582 ** forgot the copy's --- why wasn't this detected??
6585 ret->sets = sRefSet_copy (ret->sets, b->sets);
6586 ret->msets = sRefSet_copy (ret->msets, b->msets);
6587 ret->uses = sRefSet_copy (ret->uses, b->uses);
6589 /* left this out --- causes and aliasing bug (infinite loop)
6590 should be detected?? */
6592 exprNode_checkUse (ret, b->sref, b->loc);
6593 exprNode_mergeUSs (ret, t);
6594 exprNode_checkUse (ret, t->sref, t->loc);
6596 ret->exitCode = b->exitCode;
6597 ret->canBreak = b->canBreak;
6598 ret->mustBreak = b->mustBreak;
6602 context_exitDoWhileClause (t);
6604 ret->kind = XPR_DOWHILE;
6605 ret->edata = exprData_makePair (t, b);
6609 exprNode exprNode_for (/*@keep@*/ exprNode inc, /*@keep@*/ exprNode body)
6612 bool emptyErr = FALSE;
6614 if (context_maybeSet (FLG_FOREMPTY))
6616 if (exprNode_isEmptyStatement (body))
6618 emptyErr = optgenerror
6621 ("Body of for statement is empty"),
6622 exprNode_loc (body));
6626 if (!emptyErr && context_maybeSet (FLG_FORBLOCK))
6628 if (exprNode_isDefined (body)
6629 && !exprNode_isBlock (body))
6631 if (context_inIterDef ()
6632 && (body->kind == XPR_STMTLIST
6633 || body->kind == XPR_TOK))
6639 voptgenerror (FLG_FORBLOCK,
6641 ("Body of for statement is not a block: %s",
6642 exprNode_unparse (body)),
6643 exprNode_loc (body));
6649 ** for ud purposes: (alreadly) init -> test -> (now) LOOP: body + inc + test
6652 if (exprNode_isError (body))
6654 ret = exprNode_createPartialCopy (inc);
6658 ret = exprNode_createPartialCopy (body);
6660 ret->exitCode = exitkind_makeConditional (body->exitCode);
6662 exprNode_mergeUSs (inc, body);
6664 if (exprNode_isDefined (inc))
6668 context_setMessageAnnote (cstring_makeLiteral ("in post loop increment"));
6671 tmp = exprNode_effect (exprData_getTripleInc (inc->edata));
6672 exprNode_freeShallow (tmp);
6674 context_clearMessageAnnote ();
6675 context_setMessageAnnote (cstring_makeLiteral ("in post loop test"));
6677 tmp = exprNode_effect (exprData_getTripleTest (inc->edata));
6678 exprNode_freeShallow (tmp);
6680 context_clearMessageAnnote ();
6682 ret->uses = sRefSet_copy (ret->uses, inc->uses);
6683 ret->sets = sRefSet_copy (ret->sets, inc->sets);
6684 ret->msets = sRefSet_copy (ret->msets, inc->msets);
6688 ret->kind = XPR_FOR;
6689 ret->edata = exprData_makePair (inc, body);
6691 if (exprNode_isDefined (inc)) {
6692 exprNode test = exprData_getTripleTest (inc->edata);
6694 if (exprNode_isUndefined (test)) {
6695 if (exprNode_isDefined (body)) {
6696 if (!body->canBreak) {
6697 /* Really, it means never reached. */
6698 ret->exitCode = XK_MUSTEXIT;
6708 ** for (init; test; inc)
6711 ** while (test) { body; inc; }
6713 ** Now: check use of init (may set vars for test)
6714 ** check use of test
6718 /*@observer@*/ guardSet exprNode_getForGuards (exprNode pred)
6722 if (exprNode_isError (pred)) return guardSet_undefined;
6724 llassert (pred->kind == XPR_FORPRED);
6726 test = exprData_getTripleTest (pred->edata);
6728 if (!exprNode_isError (test))
6730 return (test->guards);
6733 return guardSet_undefined;
6736 exprNode exprNode_whilePred (/*@only@*/ exprNode test)
6738 exprNode ret = exprNode_createSemiCopy (test);
6740 if (exprNode_isDefined (test))
6742 exprNode_copySets (ret, test);
6743 exprNode_checkPred (cstring_makeLiteralTemp ("while"), test);
6744 exprNode_checkUse (ret, test->sref, test->loc);
6746 exprNode_produceGuards (test);
6748 ret->guards = guardSet_copy (test->guards);
6751 ret->edata = exprData_makeSingle (test);
6752 ret->kind = XPR_WHILEPRED;
6756 exprNode exprNode_forPred (/*@only@*/ exprNode init, /*@only@*/ exprNode test,
6757 /*@only@*/ exprNode inc)
6762 ** for ud purposes: init -> test -> LOOP: [ body, inc ]
6765 exprNode_checkPred (cstring_makeLiteralTemp ("for"), test);
6767 if (!exprNode_isError (inc))
6769 ret = exprNode_createPartialCopy (inc);
6773 if (!exprNode_isError (init))
6775 ret = exprNode_createPartialCopy (init);
6777 else if (!exprNode_isError (test))
6779 ret = exprNode_createPartialCopy (test);
6783 ret = exprNode_createUnknown ();
6787 exprNode_mergeUSs (ret, init);
6789 if (exprNode_isDefined (init))
6791 exprNode_checkUse (ret, init->sref, init->loc);
6794 exprNode_mergeUSs (ret, test);
6796 if (exprNode_isDefined (test))
6798 exprNode_checkUse (ret, test->sref, test->loc);
6801 ret->kind = XPR_FORPRED;
6802 ret->edata = exprData_makeFor (init, test, inc);
6806 /*@notnull@*/ /*@only@*/ exprNode exprNode_goto (/*@only@*/ cstring label)
6808 exprNode ret = exprNode_createUnknown ();
6810 if (context_inMacro ())
6812 voptgenerror (FLG_MACROSTMT,
6813 message ("Macro %s uses goto (not functional)",
6814 context_inFunctionName ()),
6818 ret->kind = XPR_GOTO;
6819 ret->edata = exprData_makeLiteral (label);
6820 ret->mustBreak = TRUE;
6821 ret->exitCode = XK_GOTO;
6822 ret->canBreak = TRUE;
6826 exprNode exprNode_continue (/*@only@*/ lltok l, int qcontinue)
6828 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
6830 ret->kind = XPR_CONTINUE;
6831 ret->edata = exprData_makeTok (l);
6832 ret->canBreak = TRUE;
6833 ret->mustBreak = TRUE;
6835 if (qcontinue == QSAFEBREAK)
6839 else if (qcontinue == QINNERCONTINUE)
6841 if (!context_inDeepLoop ())
6844 (FLG_LOOPLOOPCONTINUE,
6845 cstring_makeLiteral ("Continue statement marked with innercontinue "
6846 "is not inside a nested loop"),
6847 exprNode_loc (ret));
6850 else if (qcontinue == BADTOK)
6852 if (context_inDeepLoop ())
6855 (FLG_LOOPLOOPCONTINUE,
6856 cstring_makeLiteral ("Continue statement in nested loop"),
6857 exprNode_loc (ret));
6862 llbuglit ("exprNode_continue: bad qcontinue");
6868 exprNode exprNode_break (/*@only@*/ lltok l, int bqual)
6870 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
6871 clause breakClause = context_breakClause ();
6873 ret->kind = XPR_BREAK;
6874 ret->edata = exprData_makeTok (l);
6875 ret->canBreak = TRUE;
6876 ret->mustBreak = TRUE;
6878 if (breakClause == NOCLAUSE)
6882 cstring_makeLiteral ("Break not inside while, for or switch statement"),
6883 exprNode_loc (ret));
6887 if (bqual != BADTOK)
6894 if (breakClause == SWITCHCLAUSE)
6896 if (!context_inDeepSwitch ())
6898 voptgenerror (FLG_SYNTAX,
6900 ("Break preceded by innerbreak is not in a deep switch"),
6901 exprNode_loc (ret));
6906 if (!context_inDeepLoop ())
6908 voptgenerror (FLG_SYNTAX,
6910 ("Break preceded by innerbreak is not in a deep loop"),
6911 exprNode_loc (ret));
6916 if (breakClause == SWITCHCLAUSE)
6918 voptgenerror (FLG_SYNTAX,
6920 ("Break preceded by loopbreak is breaking a switch"),
6921 exprNode_loc (ret));
6925 if (breakClause != SWITCHCLAUSE)
6929 message ("Break preceded by switchbreak is breaking %s",
6930 cstring_makeLiteralTemp
6931 ((breakClause == WHILECLAUSE
6932 || breakClause == DOWHILECLAUSE) ? "a while loop"
6933 : (breakClause == FORCLAUSE) ? "a for loop"
6934 : (breakClause == ITERCLAUSE) ? "an iterator"
6936 exprNode_loc (ret));
6944 if (breakClause == SWITCHCLAUSE)
6946 clause nextBreakClause = context_nextBreakClause ();
6948 switch (nextBreakClause)
6950 case NOCLAUSE: break;
6956 (FLG_LOOPSWITCHBREAK,
6957 cstring_makeLiteral ("Break statement in switch inside loop"),
6958 exprNode_loc (ret));
6962 (FLG_SWITCHSWITCHBREAK,
6963 cstring_makeLiteral ("Break statement in switch inside switch"),
6964 exprNode_loc (ret));
6971 if (context_inDeepLoop ())
6975 cstring_makeLiteral ("Break statement in nested loop"),
6976 exprNode_loc (ret));
6980 if (context_inDeepLoopSwitch ())
6983 (FLG_SWITCHLOOPBREAK,
6984 cstring_makeLiteral ("Break statement in loop inside switch"),
6985 exprNode_loc (ret));
6995 exprNode exprNode_nullReturn (/*@only@*/ lltok t)
6997 fileloc loc = lltok_getLoc (t);
6998 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
7000 context_returnFunction ();
7001 exprChecks_checkNullReturn (loc);
7003 ret->kind = XPR_NULLRETURN;
7004 ret->edata = exprData_makeTok (t);
7005 ret->exitCode = XK_MUSTRETURN;
7009 exprNode exprNode_return (/*@only@*/ exprNode e)
7013 if (exprNode_isError (e))
7015 ret = exprNode_createUnknown ();
7019 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (e->loc));
7021 exprNode_checkUse (ret, e->sref, e->loc);
7022 exprNode_checkReturn (e);
7025 context_returnFunction ();
7026 ret->kind = XPR_RETURN;
7027 ret->edata = exprData_makeSingle (e);
7028 ret->exitCode = XK_MUSTRETURN;
7033 exprNode exprNode_comma (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
7037 if (exprNode_isError (e1))
7039 if (exprNode_isError (e2))
7041 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
7045 ret = exprNode_createPartialCopy (e2);
7046 exprNode_checkUse (ret, e2->sref, e2->loc);
7047 ret->sref = e2->sref;
7052 ret = exprNode_createPartialCopy (e1);
7054 exprNode_checkUse (ret, e1->sref, e1->loc);
7056 if (!exprNode_isError (e2))
7058 exprNode_mergeUSs (ret, e2);
7059 exprNode_checkUse (ret, e2->sref, e2->loc);
7060 ret->sref = e2->sref;
7064 ret->kind = XPR_COMMA;
7065 ret->edata = exprData_makePair (e1, e2);
7067 if (exprNode_isDefined (e1))
7069 if (exprNode_isDefined (e2))
7073 if (exprNode_mustEscape (e1) || e1->mustBreak)
7077 message ("Second clause of comma expression is unreachable: %s",
7078 exprNode_unparse (e2)),
7082 ret->exitCode = exitkind_combine (e1->exitCode, e2->exitCode);
7083 ret->mustBreak = e1->mustBreak || e2->mustBreak;
7084 ret->canBreak = e1->canBreak || e2->canBreak;
7088 if (exprNode_mustEscape (e1) || e1->mustBreak)
7092 message ("Second clause of comma expression is unreachable: %s",
7093 exprNode_unparse (e2)),
7097 ret->exitCode = e1->exitCode;
7098 ret->canBreak = e1->canBreak;
7103 if (exprNode_isDefined (e2))
7105 ret->exitCode = e2->exitCode;
7106 ret->mustBreak = e2->mustBreak;
7107 ret->canBreak = e2->canBreak;
7114 static bool exprNode_checkOneInit (/*@notnull@*/ exprNode el, exprNode val)
7116 ctype t1 = exprNode_getType (el);
7117 ctype t2 = exprNode_getType (val);
7118 bool hasError = FALSE;
7120 if (ctype_isUnknown (t1))
7122 voptgenerror (FLG_IMPTYPE,
7123 message ("Variable has unknown (implicitly int) type: %s",
7124 exprNode_unparse (el)),
7128 el->typ = ctype_int;
7131 if (exprNode_isDefined (val) && val->kind == XPR_INITBLOCK)
7133 exprNodeList vals = exprData_getArgs (val->edata);
7135 if (ctype_isRealAP (t1))
7140 exprNodeList_elements (vals, oneval)
7142 cstring istring = message ("%d", i);
7145 (exprNode_fakeCopy (el),
7146 exprNode_numLiteral (ctype_int, istring,
7147 fileloc_copy (el->loc), i));
7149 if (exprNode_isDefined (newel))
7151 if (exprNodeList_size (vals) == 1
7152 && ctype_isString (exprNode_getType (oneval))
7153 && ctype_isChar (exprNode_getType (newel)))
7155 exprNode_freeIniter (newel);
7159 if (exprNode_checkOneInit (newel, oneval))
7164 if (nerrors > 3 && exprNodeList_size (vals) > 6)
7167 (message ("Additional initialization errors "
7168 "for %s not reported",
7169 exprNode_unparse (el)),
7171 exprNode_freeIniter (newel);
7176 exprNode_freeIniter (newel);
7181 exprNode_freeIniter (newel);
7186 cstring_free (istring);
7189 } end_exprNodeList_elements;
7192 else if (ctype_isStruct (ctype_realType (t1)))
7194 uentryList fields = ctype_getFields (t1);
7197 if (uentryList_size (fields) != exprNodeList_size (vals))
7199 if (uentryList_size (fields) > exprNodeList_size (vals))
7201 hasError = optgenerror
7203 message ("Initializer block for "
7204 "%s has %d field%p, but %s has %d field%p: %q",
7205 exprNode_unparse (el),
7206 exprNodeList_size (vals),
7208 uentryList_size (fields),
7209 exprNodeList_unparse (vals)),
7214 hasError = optgenerror
7216 message ("Initializer block for "
7217 "%s has %d field%p, but %s has %d field%p: %q",
7218 exprNode_unparse (el),
7219 exprNodeList_size (vals),
7221 uentryList_size (fields),
7222 exprNodeList_unparse (vals)),
7228 exprNodeList_elements (vals, oneval)
7230 uentry thisfield = uentryList_getN (fields, i);
7232 exprNode_fieldAccess (exprNode_fakeCopy (el),
7233 uentry_getName (thisfield));
7235 if (exprNode_isDefined (newel))
7237 if (exprNode_checkOneInit (newel, oneval))
7242 exprNode_freeIniter (newel);
7246 } end_exprNodeList_elements;
7251 hasError = optgenerror
7253 message ("Initializer block used for "
7254 "%s where %t is expected: %s",
7255 exprNode_unparse (el), t1, exprNode_unparse (val)),
7261 if (exprNode_isDefined (val))
7263 doAssign (el, val, TRUE);
7265 if (!exprNode_matchType (t1, val))
7267 hasError = gentypeerror
7269 message ("Initial value of %s is type %t, "
7271 exprNode_unparse (el),
7272 t2, t1, exprNode_unparse (val)),
7281 exprNode exprNode_makeInitialization (/*@only@*/ idDecl t,
7282 /*@only@*/ exprNode e)
7284 uentry ue = usymtab_lookup (idDecl_observeId (t));
7285 bool isUsed = uentry_isUsed (ue);
7286 exprNode ret = exprNode_fromIdentifierAux (ue);
7287 ctype ct = ctype_realishType (ret->typ);
7290 if (ctype_isUnknown (ct))
7292 voptgenerror (FLG_IMPTYPE,
7293 message ("Variable has unknown (implicitly int) type: %s",
7294 idDecl_getName (t)),
7295 exprNode_isDefined (e) ? exprNode_loc (e) : g_currentloc);
7300 if (exprNode_isError (e))
7302 e = exprNode_createUnknown ();
7305 /* error: assume initializer is defined */
7306 sRef_setDefined (ret->sref, loc);
7310 loc = exprNode_loc (e);
7315 ** was addSafeUse --- what's the problem?
7317 ** int x = 3, y = x ?
7320 exprNode_checkUse (ret, e->sref, e->loc);
7322 if (ctype_isUnknown (e->typ) && uentry_isValid (ue))
7324 exprNode lhs = exprNode_createId (ue);
7327 ** static storage should be undefined before initializing
7330 if (uentry_isStatic (ue))
7332 sRef_setDefState (lhs->sref, SS_PARTIAL, fileloc_undefined);
7335 (void) exprNode_checkOneInit (lhs, e);
7337 if (uentry_isStatic (ue))
7339 sRef_setDefState (lhs->sref, SS_DEFINED, fileloc_undefined);
7342 exprNode_free (lhs);
7346 if (!exprNode_matchType (ct, e))
7348 if (exprNode_isZero (e) && ctype_isArrayPtr (ct))
7355 (exprNode_getType (e), e, exprNode_getType (ret), ret,
7357 ("Variable %s initialized to type %t, expects %t: %s",
7358 exprNode_unparse (ret), exprNode_getType (e),
7359 exprNode_getType (ret),
7360 exprNode_unparse (e)),
7366 if (uentry_isStatic (ue))
7368 sRef_setDefState (ret->sref, SS_PARTIAL, fileloc_undefined);
7371 doAssign (ret, e, TRUE);
7373 if (uentry_isStatic (ue))
7375 sRef_setDefState (ret->sref, SS_DEFINED, fileloc_undefined);
7379 if (context_inIterDef ())
7381 /* should check if it is yield */
7382 uentry_setUsed (ue, loc);
7386 if (!isUsed) /* could be @unused@-qualified variable */
7388 uentry_setNotUsed (ue);
7392 ret->exitCode = XK_NEVERESCAPE;
7393 ret->mustBreak = FALSE;
7396 ** Must be before new kind is assigned!
7399 exprData_free (ret->edata, ret->kind);
7401 ret->kind = XPR_INIT;
7402 ret->edata = exprData_makeInit (t, e);
7403 exprNode_mergeUSs (ret, e);
7407 exprNode exprNode_iter (/*@observer@*/ uentry name,
7408 /*@only@*/ exprNodeList alist,
7409 /*@only@*/ exprNode body,
7410 /*@observer@*/ uentry end)
7415 llassert (uentry_isValid (name));
7417 uentry_setUsed (name, exprNode_loc (body));
7419 ret = exprNode_createPartialCopy (body);
7420 iname = uentry_getName (name);
7422 if (uentry_isInvalid (end))
7425 message ("Iter %s not balanced with end_%s", iname, iname));
7429 cstring ename = uentry_getName (end);
7431 if (!cstring_equalPrefix (ename, "end_"))
7433 llerror (FLG_ITER, message ("Iter %s not balanced with end_%s: %s",
7434 iname, iname, ename));
7438 if (!cstring_equal (iname, cstring_suffix (ename, 4)))
7441 message ("Iter %s not balanced with end_%s: %s",
7442 iname, iname, ename));
7446 cstring_free (ename);
7449 context_exitIterClause (body);
7451 ret->kind = XPR_ITER;
7452 ret->edata = exprData_makeIter (name, alist, body, end);
7454 if (uentry_isIter (name))
7456 (void) checkArgsReal (name, body,
7457 uentry_getParams (name), alist, TRUE, ret);
7460 cstring_free (iname);
7466 exprNode_iterNewId (/*@only@*/ cstring s)
7468 exprNode e = exprNode_new ();
7469 uentry ue = uentryList_getN (uentry_getParams (getCurrentIter ()), iterParamNo ());
7471 llassert (processingIterVars ());
7473 e->loc = context_getSaveLocation ();
7475 if (fileloc_isUndefined (e->loc))
7477 fileloc_free (e->loc);
7478 e->loc = fileloc_copy (g_currentloc);
7481 e->uses = sRefSet_new ();
7482 e->sets = sRefSet_new ();
7483 e->msets = sRefSet_new ();
7485 e->val = multiVal_unknown ();
7486 e->guards = guardSet_new ();
7488 e->isJumpPoint = FALSE;
7489 e->exitCode = XK_NEVERESCAPE;
7491 /*> missing fields, detected by lclint <*/
7492 e->canBreak = FALSE;
7493 e->mustBreak = FALSE;
7494 e->etext = cstring_undefined;
7496 if (uentry_isYield (ue))
7498 uentry uue = uentry_makeVariable (s, uentry_getType (ue),
7499 fileloc_copy (e->loc),
7503 uue = usymtab_supEntrySrefReturn (uue);
7505 sr = uentry_getSref (uue);
7506 sRef_mergeStateQuiet (sr, uentry_getSref (ue));
7507 sr = uentry_getSref (uue);
7508 sRef_setDefined (sr, e->loc);
7510 e->typ = uentry_getType (uue);
7512 e->edata = exprData_makeId (uue);
7513 uentry_setUsed (uue, g_currentloc);
7519 sRef_setGlobalScope ();
7520 uue = uentry_makeVariableLoc (s, ctype_unknown);
7522 e->typ = ctype_unknown;
7523 e->edata = exprData_makeId (uue);
7525 uentry_setUsed (uue, e->loc);
7526 uentry_setHasNameError (uue);
7528 if (context_getFlag (FLG_REPEATUNRECOG))
7530 uentry_markOwned (uue);
7534 usymtab_supGlobalEntry (uue);
7537 sRef_clearGlobalScope ();
7539 voptgenerror (FLG_UNRECOG, message ("Unrecognized identifier: %s", s),
7546 exprNode_defineConstraints(e);
7551 exprNode_iterExpr (/*@returned@*/ exprNode e)
7553 if (!processingIterVars ())
7555 llcontbuglit ("checkIterParam: not in iter");
7559 if (uentry_isYield (uentryList_getN (uentry_getParams (getCurrentIter ()),
7562 if (exprNode_isDefined (e))
7564 if (fileloc_isDefined (e->loc))
7568 message ("Yield parameter is not simple identifier: %s",
7569 exprNode_unparse (e)),
7576 message ("Yield parameter is not simple identifier: %s",
7577 exprNode_unparse (e)),
7587 exprNode_iterId (/*@observer@*/ uentry c)
7591 llassert (processingIterVars ());
7593 ue = uentryList_getN (uentry_getParams (getCurrentIter ()),
7596 if (uentry_isYield (ue))
7598 ctype ct = uentry_getType (ue);
7599 exprNode e = exprNode_createPlain (ct);
7600 cstring name = uentry_getName (c);
7601 uentry le = uentry_makeVariable (name, ct, fileloc_undefined, FALSE);
7603 uentry_setUsed (ue, g_currentloc);
7604 uentry_setHasNameError (ue);
7606 cstring_free (name);
7609 e->edata = exprData_makeId (le);
7610 e->loc = context_getSaveLocation ();
7611 e->sref = uentry_getSref (le);
7613 usymtab_supEntrySref (le);
7615 if (!context_inHeader ())
7619 message ("Yield parameter shadows local declaration: %q",
7620 uentry_getName (c)),
7621 fileloc_isDefined (e->loc) ? e->loc : g_currentloc))
7623 uentry_showWhereDeclared (c);
7630 return (exprNode_fromIdentifierAux (c));
7633 exprNode exprNode_iterStart (/*@observer@*/ uentry name, /*@only@*/ exprNodeList alist)
7635 exprNode ret = exprNode_create (ctype_unknown);
7637 ret->kind = XPR_ITERCALL;
7638 ret->edata = exprData_makeIterCall (name, alist);
7640 if (uentry_isIter (name))
7642 uentryList params = uentry_getParams (name);
7644 if (context_inIterDef ()
7645 && uentryList_size (params) == exprNodeList_size (alist))
7649 exprNodeList_elements (alist, arg)
7651 uentry parg = uentryList_getN (params, i);
7653 if (uentry_isYield (parg))
7655 uentry ue = exprNode_getUentry (arg);
7657 if (uentry_isValid (ue))
7664 } end_exprNodeList_elements;
7667 (void) checkArgsReal (name, ret, params, alist, TRUE, ret);
7668 checkUnspecCall (ret, params, alist);
7674 /*@exposed@*/ sRef exprNode_getSref (exprNode e)
7676 if (exprNode_isDefined (e))
7679 if (e->sref == defref) /*@noaccess sRef@*/
7682 e->sref = sRef_makeUnknown ();
7683 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
7694 return sRef_undefined;
7698 /*@observer@*/ cstring
7699 exprNode_unparseFirst (exprNode e)
7701 if (exprNode_isDefined (e))
7705 if (e->kind == XPR_STMTLIST
7706 || e->kind == XPR_COMMA || e->kind == XPR_COND)
7708 exprNode first = exprData_getPairA (e->edata);
7710 if (exprNode_isDefined (first))
7712 return (exprNode_unparseFirst (exprData_getPairA (e->edata)));
7716 return (cstring_makeLiteralTemp ("..."));
7720 ret = cstring_elide (exprNode_unparse (e), 20);
7721 cstring_markOwned (ret);
7727 return cstring_makeLiteralTemp ("<error>");
7731 /*@observer@*/ cstring
7732 exprNode_unparse (exprNode e)
7734 if (exprNode_isError (e))
7736 return cstring_makeLiteralTemp ("<error>");
7739 if (cstring_isDefined (e->etext))
7745 cstring ret = exprNode_doUnparse (e);
7747 /*@-modifies@*/ /* benevolent */
7754 /*@observer@*/ fileloc
7755 exprNode_loc (exprNode e)
7757 if (exprNode_isError (e))
7759 return (g_currentloc);
7768 ** executes exprNode e
7769 ** recursively rexecutes as though in original parse using
7770 ** information in e->edata
7773 static /*@only@*/ exprNodeList exprNodeList_effect (exprNodeList e)
7775 exprNodeList ret = exprNodeList_new ();
7777 exprNodeList_elements (e, current)
7779 exprNodeList_addh (ret, exprNode_effect (current));
7780 } end_exprNodeList_elements;
7785 static /*@only@*/ exprNode exprNode_effect (exprNode e)
7786 /*@globals internalState@*/
7788 bool innerEffect = inEffect;
7794 context_clearJustPopped ();
7796 if (exprNode_isError (e))
7798 ret = exprNode_undefined;
7803 ** Turn off expose and dependent transfer checking.
7804 ** Need to pass exposed internal nodes,
7805 ** [ copying would be a waste! ]
7806 ** [ Actually, I think I wasted a lot more time than its worth ]
7807 ** [ trying to do this. ]
7811 /*@-observertrans@*/
7812 /*@-dependenttrans@*/
7819 ret = exprNode_addParens (exprData_getUopTok (data),
7820 exprNode_effect (exprData_getUopNode (data)));
7823 ret = exprNode_assign (exprNode_effect (exprData_getOpA (data)),
7824 exprNode_effect (exprData_getOpB (data)),
7825 exprData_getOpTok (data));
7828 ret = exprNode_undefined;
7831 ret = exprNode_functionCall (exprNode_effect (exprData_getFcn (data)),
7832 exprNodeList_effect (exprData_getArgs (data)));
7845 cstring id = exprData_getId (data);
7846 uentry ue = usymtab_lookupSafe (id);
7848 ret = exprNode_fromIdentifierAux (ue);
7849 ret->loc = fileloc_update (ret->loc, e->loc);
7856 ret = exprNode_arrayFetch (exprNode_effect (exprData_getPairA (data)),
7857 exprNode_effect (exprData_getPairB (data)));
7860 ret = exprNode_op (exprNode_effect (exprData_getOpA (data)),
7861 exprNode_effect (exprData_getOpB (data)),
7862 exprData_getOpTok (data));
7866 ret = exprNode_postOp (exprNode_effect (exprData_getUopNode (data)),
7867 exprData_getUopTok (data));
7870 ret = exprNode_preOp (exprNode_effect (exprData_getUopNode (data)),
7871 exprData_getUopTok (data));
7883 ret = exprNode_vaArg (exprData_getCastTok (data),
7884 exprNode_effect (exprData_getCastNode (data)),
7885 exprData_getCastType (data));
7889 ret = exprNode_cast (exprData_getCastTok (data),
7890 exprNode_effect (exprData_getCastNode (data)),
7891 exprData_getCastType (data));
7894 ret = exprNode_iterStart (exprData_getIterCallIter (data),
7896 (exprData_getIterCallArgs (data)));
7900 ret = exprNode_iter (exprData_getIterSname (data),
7901 exprNodeList_effect (exprData_getIterAlist (data)),
7902 exprNode_effect (exprData_getIterBody (data)),
7903 exprData_getIterEname (data));
7907 ret = exprNode_for (exprNode_effect (exprData_getPairA (data)),
7908 exprNode_effect (exprData_getPairB (data)));
7912 ret = exprNode_forPred (exprNode_effect (exprData_getTripleInit (data)),
7913 exprNode_effect (exprData_getTripleTest (data)),
7914 exprNode_effect (exprData_getTripleInc (data)));
7918 ret = exprNode_createTok (exprData_getTok (data));
7922 ret = exprNode_goto (exprData_getLiteral (data));
7923 ret->loc = fileloc_update (ret->loc, e->loc);
7927 ret = exprNode_continue (exprData_getTok (data), QSAFEBREAK);
7931 ret = exprNode_break (exprData_getTok (data), QSAFEBREAK);
7935 ret = exprNode_return (exprNode_effect (exprData_getSingle (data)));
7938 case XPR_NULLRETURN:
7939 ret = exprNode_nullReturn (exprData_getTok (data));
7943 ret = exprNode_comma (exprNode_effect (exprData_getPairA (data)),
7944 exprNode_effect (exprData_getPairB (data)));
7948 ret = exprNode_cond (exprNode_effect (exprData_getTriplePred (data)),
7949 exprNode_effect (exprData_getTripleTrue (data)),
7950 exprNode_effect (exprData_getTripleFalse (data)));
7953 ret = exprNode_if (exprNode_effect (exprData_getPairA (data)),
7954 exprNode_effect (exprData_getPairB (data)));
7958 ret = exprNode_ifelse (exprNode_effect (exprData_getTriplePred (data)),
7959 exprNode_effect (exprData_getTripleTrue (data)),
7960 exprNode_effect (exprData_getTripleFalse (data)));
7963 ret = exprNode_whilePred (exprData_getSingle (data));
7967 ret = exprNode_while (exprNode_effect (exprData_getPairA (data)),
7968 exprNode_effect (exprData_getPairB (data)));
7972 ret = exprNode_doWhile (exprNode_effect (exprData_getPairA (data)),
7973 exprNode_effect (exprData_getPairB (data)));
7977 ret = exprNode_makeBlock (exprNode_effect (exprData_getSingle (data)));
7981 ret = exprNode_statement (exprNode_effect (exprData_getUopNode (data)),
7982 exprData_getUopTok (data));
7986 ret = exprNode_concat (exprNode_effect (exprData_getPairA (data)),
7987 exprNode_effect (exprData_getPairB (data)));
7992 ret = exprNode_caseMarker
7993 (exprNode_effect (exprData_getSingle (data)),
7999 ret = exprNode_createTok (exprData_getTok (data));
8003 ret = exprNode_switch (exprNode_effect (exprData_getPairA (data)),
8004 exprNode_effect (exprData_getPairB (data)));
8008 ret = exprNode_makeInitialization
8009 (exprData_getInitId (data),
8010 exprNode_effect (exprData_getInitNode (data)));
8014 ret = exprNode_fieldAccess (exprNode_effect (exprData_getFieldNode (data)),
8015 cstring_copy (exprData_getFieldName (data)));
8019 ret = exprNode_arrowAccess (exprNode_effect (exprData_getFieldNode (data)),
8020 cstring_copy (exprData_getFieldName (data)));
8023 case XPR_STRINGLITERAL:
8037 /*@=observertrans@*/
8039 /*@=dependenttrans@*/
8050 static /*@observer@*/ cstring exprNode_rootVarName (exprNode e)
8055 if (exprNode_isError (e))
8057 return cstring_undefined;
8065 ret = exprNode_rootVarName (exprData_getUopNode (data));
8068 ret = exprNode_rootVarName (exprData_getOpA (data));
8072 ret = exprData_getId (data);
8097 case XPR_NULLRETURN:
8120 case XPR_STRINGLITERAL:
8121 ret = cstring_undefined;
8129 static /*@only@*/ cstring exprNode_doUnparse (exprNode e)
8134 if (exprNode_isError (e))
8136 static /*@only@*/ cstring error = cstring_undefined;
8138 if (!cstring_isDefined (error))
8140 error = cstring_makeLiteral ("<error>");
8151 ret = message ("(%s)", exprNode_unparse (exprData_getUopNode (e->edata)));
8154 ret = message ("%s %s %s",
8155 exprNode_unparse (exprData_getOpA (data)),
8156 lltok_unparse (exprData_getOpTok (data)),
8157 exprNode_unparse (exprData_getOpB (data)));
8160 ret = message ("%s(%q)",
8161 exprNode_unparse (exprData_getFcn (data)),
8162 exprNodeList_unparse (exprData_getArgs (data)));
8165 ret = message ("{ %q }", exprNodeList_unparse (exprData_getArgs (data)));
8168 ret = cstring_undefined;
8171 ret = message ("%s:", exprData_getId (data));
8175 ret = cstring_copy (exprData_getId (data));
8178 ret = message ("%s[%s]", exprNode_unparse (exprData_getPairA (data)),
8179 exprNode_unparse (exprData_getPairB (data)));
8182 ret = message ("<body>");
8185 ret = message ("%s %s %s",
8186 exprNode_unparse (exprData_getOpA (data)),
8187 lltok_unparse (exprData_getOpTok (data)),
8188 exprNode_unparse (exprData_getOpB (data)));
8192 ret = message ("%s%s",
8193 lltok_unparse (exprData_getUopTok (data)),
8194 exprNode_unparse (exprData_getUopNode (data)));
8198 ret = message ("%s%s",
8199 exprNode_unparse (exprData_getUopNode (data)),
8200 lltok_unparse (exprData_getUopTok (data)));
8204 ret = message ("offsetof(%s,%q)",
8205 ctype_unparse (qtype_getType (exprData_getOffsetType (data))),
8206 cstringList_unparseSep (exprData_getOffsetName (data), cstring_makeLiteralTemp (".")));
8210 ret = message ("sizeof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
8214 ret = message ("sizeof(%s)", exprNode_unparse (exprData_getSingle (data)));
8218 ret = message ("alignof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
8222 ret = message ("alignof(%s)", exprNode_unparse (exprData_getSingle (data)));
8226 ret = message ("va_arg(%s, %q)",
8227 exprNode_unparse (exprData_getCastNode (data)),
8228 qtype_unparse (exprData_getCastType (data)));
8232 ret = message ("%q(%q)",
8233 uentry_getName (exprData_getIterCallIter (data)),
8234 exprNodeList_unparse (exprData_getIterCallArgs (data)));
8237 ret = message ("%q(%q) %s %q",
8238 uentry_getName (exprData_getIterSname (data)),
8239 exprNodeList_unparse (exprData_getIterAlist (data)),
8240 exprNode_unparse (exprData_getIterBody (data)),
8241 uentry_getName (exprData_getIterEname (data)));
8244 ret = message ("(%q)%s",
8245 qtype_unparse (exprData_getCastType (data)),
8246 exprNode_unparse (exprData_getCastNode (data)));
8250 ret = message ("%s %s",
8251 exprNode_unparse (exprData_getPairA (data)),
8252 exprNode_unparse (exprData_getPairB (data)));
8256 ret = message ("for (%s; %s; %s)",
8257 exprNode_unparse (exprData_getTripleInit (data)),
8258 exprNode_unparse (exprData_getTripleTest (data)),
8259 exprNode_unparse (exprData_getTripleInc (data)));
8263 ret = message ("goto %s", exprData_getLiteral (data));
8267 ret = cstring_makeLiteral ("continue");
8271 ret = cstring_makeLiteral ("break");
8275 ret = message ("return %s", exprNode_unparse (exprData_getSingle (data)));
8278 case XPR_NULLRETURN:
8279 ret = cstring_makeLiteral ("return");
8283 ret = message ("%s, %s",
8284 exprNode_unparse (exprData_getPairA (data)),
8285 exprNode_unparse (exprData_getPairB (data)));
8289 ret = message ("%s ? %s : %s",
8290 exprNode_unparse (exprData_getTriplePred (data)),
8291 exprNode_unparse (exprData_getTripleTrue (data)),
8292 exprNode_unparse (exprData_getTripleFalse (data)));
8295 ret = message ("if (%s) %s",
8296 exprNode_unparse (exprData_getPairA (data)),
8297 exprNode_unparse (exprData_getPairB (data)));
8301 ret = message ("if (%s) %s else %s",
8302 exprNode_unparse (exprData_getTriplePred (data)),
8303 exprNode_unparse (exprData_getTripleTrue (data)),
8304 exprNode_unparse (exprData_getTripleFalse (data)));
8307 ret = message ("while (%s) %s",
8308 exprNode_unparse (exprData_getPairA (data)),
8309 exprNode_unparse (exprData_getPairB (data)));
8313 ret = cstring_copy (exprNode_unparse (exprData_getSingle (data)));
8317 ret = cstring_copy (lltok_unparse (exprData_getTok (data)));
8321 ret = message ("do { %s } while (%s)",
8322 exprNode_unparse (exprData_getPairB (data)),
8323 exprNode_unparse (exprData_getPairA (data)));
8327 ret = message ("{ %s }", exprNode_unparseFirst (exprData_getSingle (data)));
8331 ret = cstring_copy (exprNode_unparse (exprData_getUopNode (data)));
8335 ret = message ("%s; %s",
8336 exprNode_unparse (exprData_getPairA (data)),
8337 exprNode_unparse (exprData_getPairB (data)));
8342 ret = cstring_makeLiteral ("default:");
8346 ret = message ("switch (%s) %s",
8347 exprNode_unparse (exprData_getPairA (data)),
8348 exprNode_unparse (exprData_getPairB (data)));
8353 ret = message ("case %s:",
8354 exprNode_unparse (exprData_getSingle (data)));
8358 ret = message ("%s = %s",
8359 idDecl_getName (exprData_getInitId (data)),
8360 exprNode_unparse (exprData_getInitNode (data)));
8364 ret = message ("%s.%s",
8365 exprNode_unparse (exprData_getFieldNode (data)),
8366 exprData_getFieldName (data));
8370 ret = message ("%s->%s",
8371 exprNode_unparse (exprData_getFieldNode (data)),
8372 exprData_getFieldName (data));
8375 case XPR_STRINGLITERAL:
8376 ret = cstring_copy (exprData_getLiteral (data));
8380 ret = cstring_copy (exprData_getLiteral (data));
8384 ret = cstring_makeLiteral ("<node>");
8392 exprNode_isCharLit (exprNode e)
8394 if (exprNode_isDefined (e))
8396 return (multiVal_isChar (exprNode_getValue (e)));
8405 exprNode_isNumLit (exprNode e)
8407 if (exprNode_isDefined (e))
8409 return (multiVal_isInt (exprNode_getValue (e)));
8418 exprNode_isFalseConstant (exprNode e)
8420 if (exprNode_isDefined (e))
8422 cstring s = exprNode_rootVarName (e);
8424 if (cstring_equal (s, context_getFalseName ()))
8434 exprNode_matchLiteral (ctype expected, exprNode e)
8436 if (exprNode_isDefined (e))
8438 multiVal m = exprNode_getValue (e);
8440 if (multiVal_isDefined (m))
8442 if (multiVal_isInt (m))
8444 long int val = multiVal_forceInt (m);
8446 if (ctype_isDirectBool (ctype_realishType (expected)))
8450 return FALSE; /* really?! return TRUE; allow use of 0 for FALSE */
8458 if (ctype_isRealInt (expected))
8461 ** unsigned <- [ constant >= 0 is okay ]
8464 if (ctype_isUnsigned (expected))
8473 ** No checks on sizes of integers...maybe add
8477 DPRINTF (("Here: %s => %s", exprNode_unparse (e), ctype_unparse (expected)));
8478 DPRINTF (("Type: %s / %s", ctype_unparse (exprNode_getType (e)),
8479 bool_unparse (ctype_isInt (exprNode_getType (e)))));
8481 if (context_getFlag (FLG_NUMLITERAL)
8482 && (ctype_isRegularInt (exprNode_getType (e)) || val == 0)) {
8488 return FALSE; /* evs 2000-05-17: previously, always returned TRUE */
8492 else if (ctype_isChar (expected))
8496 else if (ctype_isArrayPtr (expected))
8500 else if (ctype_isAnyFloat (expected))
8502 return (context_getFlag (FLG_NUMLITERAL));
8509 else if (multiVal_isDouble (m))
8511 if (ctype_isAnyFloat (expected))
8516 else if (multiVal_isChar (m))
8518 char val = multiVal_forceChar (m);
8520 if (ctype_isChar (expected))
8522 if (ctype_isUnsigned (expected) && ((int)val) < 0)
8543 exprNode_matchType (ctype expected, exprNode e)
8547 if (!exprNode_isDefined (e)) return TRUE;
8549 actual = ctype_realishType (exprNode_getType (e));
8551 if (ctype_match (ctype_realishType (expected), actual))
8556 llassert (!exprNode_isError (e));
8557 return (exprNode_matchLiteral (expected, e));
8561 exprNode_matchTypes (exprNode e1, exprNode e2)
8566 if (!exprNode_isDefined (e1)) return TRUE;
8567 if (!exprNode_isDefined (e2)) return TRUE;
8570 ** realish type --- keep bools, bools
8573 t1 = ctype_realishType (exprNode_getType (e1));
8574 t2 = ctype_realishType (exprNode_getType (e2));
8576 if (ctype_match (t1, t2))
8581 return (exprNode_matchLiteral (t1, e2) || exprNode_matchLiteral (t2, e1));
8589 exprNode_matchArgType (ctype ct, exprNode e)
8593 if (!exprNode_isDefined (e))
8598 et = ctype_realType (exprNode_getType (e));
8600 if (ctype_matchArg (ct, et)) return TRUE;
8602 llassert (!exprNode_isError (e));
8603 return (exprNode_matchLiteral (ct, e));
8606 static /*@only@*/ exprNodeSList
8607 exprNode_flatten (/*@dependent@*/ exprNode e) /*@*/
8609 if (exprNode_isDefined (e))
8611 if (e->kind == XPR_STMTLIST)
8613 return (exprNodeSList_append
8614 (exprNode_flatten (exprData_getPairA (e->edata)),
8615 exprNode_flatten (exprData_getPairB (e->edata))));
8617 else if (e->kind == XPR_BLOCK)
8619 return (exprNode_flatten (exprData_getSingle (e->edata)));
8623 return (exprNodeSList_singleton (e));
8627 return exprNodeSList_new ();
8630 static /*@exposed@*/ exprNode
8631 exprNode_lastStatement (/*@returned@*/ exprNode e)
8633 if (exprNode_isDefined (e))
8635 if (e->kind == XPR_STMTLIST)
8637 exprNode b = exprData_getPairB (e->edata);
8639 if (exprNode_isDefined (b))
8641 return exprNode_lastStatement (b);
8645 return exprNode_lastStatement (exprData_getPairA (e->edata));
8648 else if (e->kind == XPR_BLOCK)
8650 return (exprNode_lastStatement (exprData_getSingle (e->edata)));
8658 return exprNode_undefined;
8661 static /*@exposed@*/ exprNode
8662 exprNode_firstStatement (/*@returned@*/ exprNode e)
8664 if (exprNode_isDefined (e))
8666 if (e->kind == XPR_STMTLIST)
8668 exprNode b = exprData_getPairA (e->edata);
8670 if (exprNode_isDefined (b))
8672 return exprNode_firstStatement (b);
8676 return exprNode_firstStatement (exprData_getPairB (e->edata));
8679 else if (e->kind == XPR_BLOCK)
8681 return (exprNode_firstStatement (exprData_getSingle (e->edata)));
8689 return exprNode_undefined;
8693 exprNode_mergeUSs (exprNode res, exprNode other)
8695 if (exprNode_isDefined (res) && exprNode_isDefined (other))
8697 res->msets = sRefSet_union (res->msets, other->msets);
8698 res->sets = sRefSet_union (res->sets, other->sets);
8699 res->uses = sRefSet_union (res->uses, other->uses);
8704 exprNode_mergeCondUSs (exprNode res, exprNode other1, exprNode other2)
8706 if (exprNode_isDefined (res))
8708 if (exprNode_isDefined (other1))
8710 res->sets = sRefSet_union (res->sets, other1->sets);
8711 res->msets = sRefSet_union (res->msets, other1->msets);
8712 res->uses = sRefSet_union (res->uses, other1->uses);
8714 if (exprNode_isDefined (other2))
8716 res->sets = sRefSet_union (res->sets, other2->sets);
8717 res->msets = sRefSet_union (res->msets, other2->msets);
8718 res->uses = sRefSet_union (res->uses, other2->uses);
8726 ** Reports errors is s is not defined.
8730 exprNode_addUse (exprNode e, sRef s)
8732 if (exprNode_isDefined (e))
8734 e->uses = sRefSet_insert (e->uses, s);
8739 exprNode_checkUse (exprNode e, sRef s, fileloc loc)
8741 if (sRef_isKnown (s) && !sRef_isConst (s))
8744 ** need to check all outer types are useable
8747 DPRINTF (("Check use: %s / %s",
8748 exprNode_unparse (e), sRef_unparse (s)));
8750 exprNode_addUse (e, s);
8752 if (!context_inProtectVars ())
8755 ** only report the deepest error
8758 sRef errorRef = sRef_undefined;
8759 sRef lastRef = sRef_undefined;
8760 bool deadRef = FALSE;
8761 bool unuseable = FALSE;
8762 bool errorMaybe = FALSE;
8764 while (sRef_isValid (s) && sRef_isKnown (s))
8766 ynm readable = sRef_isReadable (s);
8768 if (!(ynm_toBoolStrict (readable)))
8770 if (ynm_isMaybe (readable))
8774 deadRef = sRef_isPossiblyDead (errorRef);
8775 unuseable = sRef_isUnuseable (errorRef);
8782 deadRef = sRef_isDead (errorRef);
8783 unuseable = sRef_isUnuseable (errorRef);
8787 if (!sRef_isPartial (s))
8789 sRef_setDefined (s, fileloc_undefined);
8793 s = sRef_getBaseSafe (s);
8796 if (sRef_isValid (errorRef))
8798 if (sRef_isValid (lastRef) && sRef_isField (lastRef)
8799 && sRef_isPointer (errorRef))
8806 if (sRef_isThroughArrayFetch (errorRef))
8809 (FLG_STRICTUSERELEASED,
8810 message ("%q %q may be used after being released",
8811 sRef_unparseKindNamePlain (errorRef),
8812 sRef_unparse (errorRef)),
8815 sRef_showRefKilled (errorRef);
8817 if (sRef_isKept (errorRef))
8819 sRef_clearAliasState (errorRef, loc);
8825 DPRINTF (("HERE: %s", sRef_unparse (errorRef)));
8829 message ("%q %q %qused after being released",
8830 sRef_unparseKindNamePlain (errorRef),
8831 sRef_unparse (errorRef),
8832 cstring_makeLiteral (errorMaybe
8836 sRef_showRefKilled (errorRef);
8838 if (sRef_isKept (errorRef))
8840 sRef_clearAliasState (errorRef, loc);
8849 message ("%q %q%qused in inconsistent state",
8850 sRef_unparseKindName (errorRef),
8851 sRef_unparseOpt (errorRef),
8852 cstring_makeLiteral (errorMaybe ? "may be " : "")),
8855 sRef_showStateInconsistent (errorRef);
8860 DPRINTF (("HERE: %s", sRef_unparse (errorRef)));
8864 message ("%q %q%qused before definition",
8865 sRef_unparseKindName (errorRef),
8866 sRef_unparseOpt (errorRef),
8867 cstring_makeLiteral (errorMaybe ? "may be " : "")),
8871 sRef_setDefined (errorRef, loc);
8873 if (sRef_isAddress (errorRef))
8875 sRef_setDefined (sRef_getRootBase (errorRef), loc);
8877 } /* end is error */
8885 checkSafeUse (exprNode e, sRef s)
8887 if (exprNode_isDefined (e) && sRef_isKnown (s))
8889 e->uses = sRefSet_insert (e->uses, s);
8894 exprNode_checkSetAny (exprNode e, /*@dependent@*/ cstring name)
8896 if (exprNode_isDefined (e))
8898 e->sets = sRefSet_insert (e->sets, sRef_makeUnconstrained (name));
8903 exprNode_checkSet (exprNode e, sRef s)
8905 sRef defines = sRef_undefined;
8907 if (sRef_isValid (s) && !sRef_isNothing (s))
8909 uentry ue = sRef_getBaseUentry (s);
8911 if (uentry_isValid (ue))
8913 uentry_setLset (ue);
8916 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
8918 voptgenerror (FLG_USEDEF,
8919 message ("Attempt to set unuseable storage: %q",
8924 if (sRef_isMeaningful (s))
8927 if (sRef_isDead (s))
8929 sRef base = sRef_getBaseSafe (s);
8931 if (sRef_isValid (base)
8932 && sRef_isDead (base))
8934 sRef_setPartial (s, exprNode_loc (e));
8937 defines = s; /* okay - modifies for only param */
8939 else if (sRef_isPartial (s))
8941 sRef eref = exprNode_getSref (e);
8943 if (!sRef_isPartial (eref))
8946 ** should do something different here???
8949 sRef_setDefinedComplete (eref, exprNode_loc (e));
8953 sRef_setPartialDefinedComplete (eref, exprNode_loc (e));
8956 if (sRef_isMeaningful (eref))
8965 else if (sRef_isAllocated (s))
8967 sRef eref = exprNode_getSref (e);
8970 if (!sRef_isAllocated (eref))
8972 sRef_setDefinedComplete (eref, exprNode_loc (e));
8976 sRef base = sRef_getBaseSafe (eref);
8978 if (sRef_isValid (base))
8980 sRef_setPdefined (base, exprNode_loc (e));
8988 sRef_setDefinedNCComplete (s, exprNode_loc (e));
8993 else /* not meaningful...but still need to insert it */
8999 if (exprNode_isDefined (e) && sRef_isValid (defines))
9001 e->sets = sRefSet_insert (e->sets, defines);
9006 exprNode_checkMSet (exprNode e, sRef s)
9008 if (sRef_isValid (s) && !sRef_isNothing (s))
9010 uentry ue = sRef_getBaseUentry (s);
9012 if (uentry_isValid (ue))
9014 uentry_setLset (ue);
9017 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
9019 voptgenerror (FLG_USEDEF,
9020 message ("Attempt to set unuseable storage: %q", sRef_unparse (s)),
9024 if (sRef_isMeaningful (s))
9026 sRef_setDefinedComplete (s, exprNode_loc (e));
9029 if (exprNode_isDefined (e))
9031 e->msets = sRefSet_insert (e->msets, s);
9037 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode fcn, uentryList params, exprNodeList args)
9039 checkAnyCall (fcn, cstring_undefined, params, args,
9040 FALSE, sRefSet_undefined, FALSE, 0);
9044 checkOneArg (uentry ucurrent, /*@notnull@*/ exprNode current,
9045 /*@dependent@*/ exprNode fcn, bool isSpec, int argno, int totargs)
9049 if (uentry_isYield (ucurrent))
9051 sRef_setDefined (exprNode_getSref (current), exprNode_loc (current));
9052 exprNode_checkSet (current, current->sref);
9056 if (uentry_isSefParam (ucurrent))
9058 sRefSet sets = current->sets;
9059 sRef ref = exprNode_getSref (current);
9061 if (sRef_isMacroParamRef (ref))
9063 uentry ue = sRef_getUentry (ref);
9065 if (!uentry_isSefParam (ue))
9070 ("Parameter %d to %s is declared sef, but "
9071 "the argument is a macro parameter declared "
9073 argno, exprNode_unparse (fcn),
9074 exprNode_unparse (current)),
9075 exprNode_loc (current));
9079 if (!sRefSet_isEmpty (sets))
9081 sRefSet reported = sRefSet_undefined;
9083 sRefSet_realElements (current->sets, el)
9085 if (sRefSet_isSameNameMember (reported, el))
9087 ; /* don't report again */
9091 if (sRef_isUnconstrained (el))
9096 ("Parameter %d to %s is declared sef, but "
9097 "the argument calls unconstrained function %s "
9098 "(no guarantee it will not modify something): %s",
9099 argno, exprNode_unparse (fcn),
9100 sRef_unconstrainedName (el),
9101 exprNode_unparse (current)),
9102 exprNode_loc (current));
9109 ("Parameter %d to %s is declared sef, but "
9110 "the argument may modify %q: %s",
9111 argno, exprNode_unparse (fcn),
9113 exprNode_unparse (current)),
9114 exprNode_loc (current));
9117 } end_sRefSet_realElements;
9121 checkPassTransfer (current, ucurrent, isSpec, fcn, argno, totargs);
9122 exprNode_mergeUSs (fcn, current);
9127 checkAnyCall (/*@dependent@*/ exprNode fcn,
9128 /*@dependent@*/ cstring fname,
9131 bool hasMods, sRefSet mods,
9136 int nargs = exprNodeList_size (args);
9141 ** concat all args ud's to f, add each arg sref as a use unless
9142 ** it was specified as "out", in which case it is a def.
9145 uentryList_reset (pn);
9150 ** if paramn is only or unique, no other arg may alias argn
9153 exprNodeList_elements (args, current)
9157 if (exprNode_isDefined (current))
9159 if ((!uentryList_isUndefined (pn) && !uentryList_isFinished (pn)))
9161 uentry ucurrent = uentryList_current (pn);
9163 if (specialArgs == 0
9164 || (paramno < specialArgs))
9166 checkOneArg (ucurrent, current, fcn, isSpec, paramno, nargs);
9168 if (context_maybeSet (FLG_ALIASUNIQUE))
9170 if (uentry_isOnly (ucurrent)
9171 || uentry_isUnique (ucurrent))
9173 checkUniqueParams (fcn, current, args,
9179 else /* uentry is undefined */
9181 if (specialArgs == 0)
9183 exprNode_checkUseParam (current);
9186 exprNode_mergeUSs (fcn, current);
9189 uentryList_advanceSafe (pn);
9190 } end_exprNodeList_elements;
9196 sRefSet_allElements (mods, s)
9199 sRef rb = sRef_getRootBase (s);
9201 if (sRef_isGlobal (rb))
9203 context_usedGlobal (rb);
9206 fb = sRef_fixBaseParam (s, args);
9208 if (!sRef_isMacroParamRef (fb))
9210 if (sRef_isNothing (fb))
9216 if (sRef_isValid (fb))
9218 uentry ue = sRef_getBaseUentry (s);
9220 if (uentry_isValid (ue))
9222 uentry_setLset (ue);
9226 fcn->sets = sRefSet_insert (fcn->sets, fb);
9229 sRef_clearDerivedComplete (s);
9230 } end_sRefSet_allElements;
9236 if (context_hasMods ())
9238 if (context_maybeSet (FLG_MODUNCON))
9242 message ("Undetected modification possible "
9243 "from call to unconstrained function %s: %s",
9245 exprNode_unparse (fcn)),
9246 exprNode_loc (fcn));
9251 if (context_maybeSet (FLG_MODUNCONNOMODS)
9252 && !(context_inIterDef () || context_inIterEnd ()))
9255 (FLG_MODUNCONNOMODS,
9256 message ("Undetected modification possible "
9257 "from call to unconstrained function %s: %s",
9259 exprNode_unparse (fcn)),
9260 exprNode_loc (fcn));
9264 exprNode_checkSetAny (fcn, fname);
9268 void exprNode_checkUseParam (exprNode current)
9270 if (exprNode_isDefined (current))
9272 exprNode_checkUse (current, current->sref, current->loc);
9277 checkNumerics (ctype tr1, ctype tr2, ctype te1, ctype te2,
9278 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
9283 if (!ctype_match (tr1, tr2))
9285 if ((ctype_isRealInt (tr1) || ctype_isReal (tr1)) &&
9286 (ctype_isRealInt (tr2) || ctype_isReal (tr2)))
9294 message ("Incompatible types for %s (%s, %s): %s %s %s",
9296 ctype_unparse (te1),
9297 ctype_unparse (te2),
9298 exprNode_unparse (e1), lltok_unparse (op),
9299 exprNode_unparse (e2)),
9302 ret = ctype_unknown;
9306 if (ctype_isForceRealNumeric (&tr1) && ctype_isForceRealNumeric (&tr2))
9308 ret = ctype_resolveNumerics (tr1, tr2);
9310 else if (!context_msgStrictOps ())
9312 if (ctype_isPointer (tr1))
9314 if (ctype_isPointer (tr2) && !exprNode_isNullValue (e2))
9318 else if (ctype_isInt (tr2))
9324 ret = ctype_unknown;
9327 else if (ctype_isPointer (tr2))
9329 if (ctype_isPointer (tr1))
9333 else if (ctype_isInt (tr1))
9339 ret = ctype_unknown;
9344 ret = ctype_resolveNumerics (tr1, tr2);
9349 int opid = lltok_getTok (op);
9350 bool comparop = (opid == EQ_OP || opid == NE_OP
9351 || opid == TLT || opid == TGT
9352 || opid == LE_OP || opid == GE_OP);
9354 if (!ctype_isNumeric (tr1) && !ctype_isNumeric (tr2))
9357 && ((ctype_isEnum (tr1) && ctype_isEnum (tr2))
9358 || (ctype_isBool (tr1) && ctype_isBool (tr2))
9359 || (ctype_isChar (tr1) && ctype_isChar (tr2))))
9365 if (ctype_sameName (te1, te2))
9369 message ("Operands of %s are non-numeric (%t): %s %s %s",
9370 lltok_unparse (op), te1,
9371 exprNode_unparse (e1), lltok_unparse (op),
9372 exprNode_unparse (e2)),
9379 message ("Operands of %s are non-numerics (%t, %t): %s %s %s",
9380 lltok_unparse (op), te1, te2,
9381 exprNode_unparse (e1), lltok_unparse (op),
9382 exprNode_unparse (e2)),
9387 else if (!ctype_isNumeric (tr1))
9391 message ("Right operand of %s is non-numeric (%t): %s %s %s",
9392 lltok_unparse (op), te1,
9393 exprNode_unparse (e1), lltok_unparse (op),
9394 exprNode_unparse (e2)),
9399 if (!ctype_isNumeric (tr2))
9403 message ("Left operand of %s is non-numeric (%t): %s %s %s",
9404 lltok_unparse (op), te2,
9405 exprNode_unparse (e1), lltok_unparse (op),
9406 exprNode_unparse (e2)),
9411 ret = ctype_unknown;
9419 abstractOpError (ctype tr1, ctype tr2, lltok op,
9420 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
9421 fileloc loc1, fileloc loc2)
9423 if (ctype_isRealAbstract (tr1) && ctype_isRealAbstract (tr2))
9425 if (ctype_match (tr1, tr2))
9429 message ("Operands of %s are abstract type (%t): %s %s %s",
9430 lltok_unparse (op), tr1,
9431 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
9438 message ("Operands of %s are abstract types (%t, %t): %s %s %s",
9439 lltok_unparse (op), tr1, tr2,
9440 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
9444 else if (ctype_isRealAbstract (tr1))
9448 message ("Left operand of %s is abstract type (%t): %s %s %s",
9449 lltok_unparse (op), tr1,
9450 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
9455 if (ctype_isRealAbstract (tr2))
9459 message ("Right operand of %s is abstract type (%t): %s %s %s",
9460 lltok_unparse (op), tr2,
9461 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
9470 ** requies e1 and e2 and not error exprNode's.
9474 ** If e1 is a component of an abstract type, and e2 is mutable and client-visible,
9475 ** the rep of the abstract type is exposed.
9477 ** The order is very important:
9479 ** check rep expose (move into check transfer)
9485 ** This isn't really a sensible procedure, but the indententation
9486 ** was getting too deep.
9490 checkOneRepExpose (sRef ysr, sRef base,
9491 /*@notnull@*/ exprNode e1,
9492 /*@notnull@*/ exprNode e2, ctype ct,
9495 if (!(sRef_isOnly (ysr) || sRef_isKeep (ysr)
9496 || sRef_isOwned (ysr) || sRef_isExposed (ysr)))
9498 if (sRef_isAnyParam (base) && !sRef_isExposed (base))
9500 if (sRef_isIReference (ysr))
9502 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
9507 ("Assignment of mutable component of parameter %q "
9508 "to component of abstract "
9509 "type %s exposes rep: %s = %s",
9510 sRef_unparse (base),
9512 exprNode_unparse (e1), exprNode_unparse (e2)),
9520 ("Assignment of mutable component of parameter %q "
9521 "(through alias %q) to component of abstract "
9522 "type %s exposes rep: %s = %s",
9523 sRef_unparse (base),
9524 sRef_unparse (e2->sref),
9526 exprNode_unparse (e1), exprNode_unparse (e2)),
9532 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
9536 message ("Assignment of mutable parameter %q "
9537 "to component of abstract type %s "
9538 "exposes rep: %s = %s",
9539 sRef_unparse (base),
9541 exprNode_unparse (e1),
9542 exprNode_unparse (e2)),
9549 message ("Assignment of mutable parameter %q "
9550 "(through alias %q) to "
9551 "component of abstract type %s exposes "
9553 sRef_unparse (base),
9554 sRef_unparse (e2->sref),
9556 exprNode_unparse (e1),
9557 exprNode_unparse (e2)),
9563 if (sRef_isGlobal (s2b))
9565 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
9569 message ("Assignment of global %q "
9571 "abstract type %s exposes rep: %s = %s",
9572 sRef_unparse (base),
9574 exprNode_unparse (e1), exprNode_unparse (e2)),
9581 message ("Assignment of global %q (through alias %q) "
9583 "abstract type %s exposes rep: %s = %s",
9584 sRef_unparse (base),
9585 sRef_unparse (e2->sref),
9587 exprNode_unparse (e1), exprNode_unparse (e2)),
9595 doAssign (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, bool isInit)
9597 if (ctype_isRealFunction (exprNode_getType (e1))
9598 && !ctype_isRealPointer (exprNode_getType (e1)))
9602 message ("Invalid left-hand side of assignment (function type %s): %s",
9603 ctype_unparse (exprNode_getType (e1)),
9604 exprNode_unparse (e1)),
9608 if (context_getFlag (FLG_ASSIGNEXPOSE) && ctype_isMutable (e2->typ))
9610 ctype t2 = exprNode_getType (e2);
9611 sRef sr = sRef_getRootBase (e1->sref);
9612 ctype ct = sRef_getType (sr);
9614 if (ctype_isAbstract (t2)
9615 && !(uentry_isMutableDatatype (usymtab_getTypeEntry (ctype_typeId (t2)))))
9617 /* it is immutable, okay to reference */
9621 if (ctype_isAbstract (ct) && sRef_isIReference (e1->sref))
9623 sRef s2b = sRef_getRootBase (e2->sref);
9625 sRef s1b = sRef_getRootBase (s1);
9628 aliases = usymtab_canAlias (e2->sref);
9630 if (!sRef_similar (s2b, s1b)
9631 && !sRef_isExposed (s1)
9632 && !(sRef_isOnly (s2b) || sRef_isKeep (s2b) || sRef_isExposed (s2b)))
9634 if (sRef_isAnyParam (s2b) && !sRef_isOnly (s2b)
9635 && !sRef_isOwned (s2b) && !sRef_isKeep (s2b)
9636 && !sRef_isExposed (s2b))
9638 if (sRef_isIReference (e2->sref))
9643 ("Assignment of mutable component of parameter %q "
9644 "to component of abstract type %s exposes rep: %s = %s",
9647 exprNode_unparse (e1), exprNode_unparse (e2)),
9654 message ("Assignment of mutable parameter %q to "
9655 "component of abstract type %s exposes rep: %s = %s",
9658 exprNode_unparse (e1), exprNode_unparse (e2)),
9663 if (sRef_isGlobal (s2b))
9667 message ("Assignment of global %q to component of "
9668 "abstract type %s exposes rep: %s = %s",
9671 exprNode_unparse (e1), exprNode_unparse (e2)),
9675 sRefSet_realElements (aliases, ysr)
9677 sRef base = sRef_getRootBase (ysr);
9679 if (sRef_similar (ysr, s2b) || sRef_similar (s1b, base)
9680 || sRef_sameName (base, s1b))
9682 ; /* error already reported or same sref */
9686 checkOneRepExpose (ysr, base, e1, e2, ct, s2b);
9688 } end_sRefSet_realElements;
9690 sRefSet_free (aliases);
9697 ** function variables don't really work...
9700 if (!ctype_isFunction (ctype_realType (e2->typ)))
9704 checkInitTransfer (e1, e2);
9708 checkAssignTransfer (e1, e2);
9713 sRef fref = e2->sref;
9715 sRef_setDefState (e1->sref, sRef_getDefState (fref), e1->loc);
9716 sRef_setNullState (e1->sref, sRef_getNullState (fref), e1->loc);
9718 /* Need to typecheck the annotation on the parameters */
9720 if (ctype_isRealFunction (e1->typ)) {
9721 uentryList e1p = ctype_argsFunction (ctype_realType (e1->typ));
9722 uentryList e2p = ctype_argsFunction (ctype_realType (e2->typ));
9724 if (!uentryList_isMissingParams (e1p)
9725 && !uentryList_isMissingParams (e2p)
9726 && uentryList_size (e1p) > 0) {
9727 if (uentryList_size (e1p) == uentryList_size (e2p)) {
9730 uentryList_elements (e1p, el1) {
9733 el2 = uentryList_getN (e2p, n);
9735 uentry_checkMatchParam (el1, el2, n, e2);
9736 } end_uentryList_elements;
9742 if (isInit && sRef_isGlobal (e1->sref))
9748 updateAliases (e1, e2);
9750 // updateEnvironment (e1, e2);
9754 checkMacroParen (exprNode e)
9756 if (exprNode_isError (e) || e->kind == XPR_CAST)
9762 if (sRef_isUnsafe (e->sref) && !exprNode_isInParens (e))
9766 message ("Macro parameter used without parentheses: %s",
9767 exprNode_unparse (e)),
9774 reflectNullTest (/*@notnull@*/ exprNode e, bool isnull)
9778 e->guards = guardSet_addTrueGuard (e->guards, e->sref);
9782 e->guards = guardSet_addFalseGuard (e->guards, e->sref);
9789 ** if e2 is a parameter or global derived location which
9790 ** can be modified (that is, e2 is a mutable abstract type,
9791 ** or a derived pointer), then e1 can alias e2.
9793 ** e1 can alias everything which e2 can alias.
9795 ** Also, if e1 is guarded, remove from guard sets!
9798 static void updateAliases (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2)
9800 if (!context_inProtectVars ())
9803 ** depends on types of e1 and e2
9808 ctype t1 = exprNode_getType (e1);
9810 /* handle pointer sRefs, record fields, arrays, etc... */
9812 if (!ctype_isRealSU (t1))
9814 sRef_copyRealDerivedComplete (s1, s2);
9817 if (ctype_isMutable (t1) && sRef_isKnown (s1))
9819 usymtab_clearAlias (s1);
9820 usymtab_addMustAlias (s1, s2);
9823 if (sRef_possiblyNull (s1) && usymtab_isGuarded (s1))
9825 usymtab_unguard (s1);
9830 exprNode exprNode_updateLocation (/*@returned@*/ exprNode e, /*@temp@*/ fileloc loc)
9832 if (exprNode_isDefined (e))
9834 e->loc = fileloc_update (e->loc, loc);
9838 e = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
9844 static void checkUniqueParams (exprNode fcn,
9845 /*@notnull@*/ exprNode current,
9847 int paramno, uentry ucurrent)
9850 sRef thisref = exprNode_getSref (current);
9853 ** Check if any argument could match this argument.
9856 exprNodeList_elements (args, icurrent)
9860 if (iparamno != paramno)
9862 sRef sr = exprNode_getSref (icurrent);
9864 if (sRef_similarRelaxed (thisref, sr))
9866 if (!sRef_isConst (thisref) && !sRef_isConst (sr))
9871 ("Parameter %d (%s) to function %s is declared %s but "
9872 "is aliased by parameter %d (%s)",
9874 exprNode_unparse (current),
9875 exprNode_unparse (fcn),
9876 alkind_unparse (uentry_getAliasKind (ucurrent)),
9877 iparamno, exprNode_unparse (icurrent)),
9883 sRefSet aliases = usymtab_canAlias (sr);
9885 sRefSet_allElements (aliases, asr)
9887 if (ctype_isUnknown (sRef_getType (thisref)))
9889 sRef_setType (thisref, uentry_getType (ucurrent));
9892 if (sRef_similarRelaxed (thisref, asr))
9894 if (sRef_isExternal (asr))
9896 if (sRef_isLocalState (thisref))
9902 sRef base = sRef_getRootBase (asr);
9904 if (!sRef_similar (sRef_getBase (asr), thisref))
9906 if (sRef_isUnique (base) || sRef_isOnly (base)
9907 || sRef_isKept (base)
9908 || (sRef_isAddress (asr) && sRef_isLocalVar (base))
9909 || (sRef_isAddress (thisref)
9910 && sRef_isLocalVar (sRef_getRootBase (thisref))))
9912 ; /* okay, no error */
9917 (FLG_MAYALIASUNIQUE,
9919 ("Parameter %d (%s) to function %s is declared %s but "
9920 "may be aliased externally by parameter %d (%s)",
9922 exprNode_unparse (current),
9923 exprNode_unparse (fcn),
9924 alkind_unparse (uentry_getAliasKind (ucurrent)),
9925 iparamno, exprNode_unparse (icurrent)),
9936 ("Parameter %d (%s) to function %s is declared %s but "
9937 "is aliased externally by parameter %d (%s) through "
9940 exprNode_unparse (current),
9941 exprNode_unparse (fcn),
9942 alkind_unparse (uentry_getAliasKind (ucurrent)),
9943 iparamno, exprNode_unparse (icurrent),
9944 sRef_unparse (asr)),
9948 } end_sRefSet_allElements;
9949 sRefSet_free (aliases);
9952 } end_exprNodeList_elements;
9955 long exprNode_getLongValue (exprNode e) {
9958 if (exprNode_hasValue (e)
9959 && multiVal_isInt (exprNode_getValue (e)))
9961 value = multiVal_forceInt (exprNode_getValue (e));
9971 fileloc exprNode_getfileloc (exprNode p_e)
9973 if (exprNode_isDefined (p_e) )
9974 return fileloc_copy ( p_e->loc );
9976 return fileloc_undefined;
9979 fileloc exprNode_getNextSequencePoint (exprNode e)
9982 ** Returns the location of the sequence point following e.
9984 ** Only works for statements (for now).
9987 if (exprNode_isDefined (e) && e->kind == XPR_STMT) {
9988 lltok t = exprData_getUopTok (e->edata);
9989 return lltok_getLoc (t);
9992 // llcontbug (message ("Cannot get next sequence point: %s", exprNode_unparse (e)));
9993 return fileloc_undefined;
10000 exprNode exprNode_fakeCopy (exprNode e)
10002 /*@-temptrans@*/ /*@-retalias@*/
10004 /*@=temptrans@*/ /*@=retalias@*/
10007 exprNode exprNode_createNew(ctype c)
10011 ret = exprNode_createPlain (c);