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) { (e)->environment=NULL; \
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;
409 e->environment = environmentTable_undefined;
410 e->requiresConstraints = constraintList_makeNew();
411 e->ensuresConstraints = constraintList_makeNew();
416 /*@observer@*/ exprNode exprNode_makeMustExit (void)
418 if (exprNode_isUndefined (mustExitNode))
420 mustExitNode = exprNode_createPlain (ctype_unknown);
421 mustExitNode->exitCode = XK_MUSTEXIT;
428 static /*@notnull@*/ /*@special@*/ exprNode exprNode_create (ctype c)
430 /*@post:isnull result->edata, result->guards, result->val,
431 result->uses, result->sets, result->msets@*/
434 exprNode e = exprNode_createPlain (c);
435 e->loc = fileloc_copy (g_currentloc);
439 static /*@notnull@*/ /*@special@*/ exprNode exprNode_createUnknown (void)
441 /*@post:isnull result->edata, result->guards,
442 result->uses, result->sets, result->msets@*/
445 return (exprNode_create (ctype_unknown));
448 static /*@notnull@*/ /*@special@*/ exprNode
449 exprNode_createLoc (ctype c, /*@keep@*/ fileloc loc)
451 /*@post:isnull result->edata, result->guards, result->val,
452 result->uses, result->sets, result->msets@*/
455 exprNode e = exprNode_createPlain (c);
461 exprNode_copySets (/*@special@*/ /*@notnull@*/ exprNode ret, exprNode e)
462 /*@defines ret->guards, ret->uses, ret->sets, ret->msets@*/
464 if (exprNode_isDefined (e))
466 ret->guards = guardSet_copy (e->guards);
467 ret->uses = sRefSet_newCopy (e->uses);
468 ret->sets = sRefSet_newCopy (e->sets);
469 ret->msets = sRefSet_newCopy (e->msets);
473 ret->guards = guardSet_undefined;
474 ret->uses = sRefSet_undefined;
475 ret->sets = sRefSet_undefined;
476 ret->msets = sRefSet_undefined;
480 static /*@notnull@*/ /*@special@*/ exprNode
481 exprNode_createPartialLocCopy (exprNode e, /*@only@*/ fileloc loc)
483 /*@post:isnull result->edata, result->etext@*/
486 exprNode ret = exprNode_new ();
488 if (exprNode_isError (e))
490 ret->typ = ctype_unknown;
491 ret->val = multiVal_undefined;
493 ret->guards = guardSet_undefined;
494 ret->uses = sRefSet_undefined;
495 ret->sets = sRefSet_undefined;
496 ret->msets = sRefSet_undefined;
501 ret->val = multiVal_copy (e->val);
503 ret->guards = guardSet_copy (e->guards);
504 ret->uses = sRefSet_newCopy (e->uses);
505 ret->sets = sRefSet_newCopy (e->sets);
506 ret->msets = sRefSet_newCopy (e->msets);
509 ret->kind = XPR_EMPTY;
511 ret->etext = cstring_undefined;
512 ret->exitCode = XK_NEVERESCAPE;
513 ret->canBreak = FALSE;
514 ret->mustBreak = FALSE;
515 ret->isJumpPoint = FALSE;
516 ret->edata = exprData_undefined;
522 static /*@notnull@*/ /*@special@*/ exprNode
523 exprNode_createPartialCopy (exprNode e)
525 /*@post:isnull result->edata, result->etext@*/
528 return (exprNode_createPartialLocCopy (e, fileloc_copy (exprNode_loc (e))));
531 static /*@notnull@*/ /*@special@*/ exprNode
532 exprNode_createPartialNVCopy (exprNode e)
534 /*@post:isnull result->edata, result->etext, result->val @*/
537 exprNode ret = exprNode_new ();
539 if (exprNode_isError (e))
541 ret->typ = ctype_unknown;
542 ret->loc = fileloc_undefined;
543 ret->guards = guardSet_undefined;
544 ret->uses = sRefSet_undefined;
545 ret->sets = sRefSet_undefined;
546 ret->msets = sRefSet_undefined;
551 ret->loc = fileloc_copy (e->loc);
552 ret->guards = guardSet_copy (e->guards);
553 ret->uses = sRefSet_newCopy (e->uses);
554 ret->sets = sRefSet_newCopy (e->sets);
555 ret->msets = sRefSet_newCopy (e->msets);
558 ret->val = multiVal_undefined;
559 ret->kind = XPR_EMPTY;
561 ret->etext = cstring_undefined;
562 ret->exitCode = XK_NEVERESCAPE;
563 ret->canBreak = FALSE;
564 ret->mustBreak = FALSE;
565 ret->isJumpPoint = FALSE;
566 ret->edata = exprData_undefined;
571 static /*@notnull@*/ /*@special@*/ exprNode
572 exprNode_createSemiCopy (exprNode e)
574 /*@post:isnull result->edata, result->etext, result->sets,
575 result->msets, result->uses, result->guards@*/
578 if (exprNode_isError (e))
580 return exprNode_createPlain (ctype_unknown);
584 exprNode ret = exprNode_new ();
587 ret->val = multiVal_copy (e->val);
588 ret->loc = fileloc_copy (e->loc);
589 ret->guards = guardSet_undefined;
590 ret->uses = sRefSet_undefined;
591 ret->sets = sRefSet_undefined;
592 ret->msets = sRefSet_undefined;
594 ret->kind = XPR_EMPTY;
596 ret->etext = cstring_undefined;
597 ret->exitCode = XK_NEVERESCAPE;
598 ret->canBreak = FALSE;
599 ret->mustBreak = FALSE;
600 ret->isJumpPoint = FALSE;
601 ret->edata = exprData_undefined;
608 exprNode_isNullValue (exprNode e)
610 if (exprNode_isDefined (e))
612 multiVal m = exprNode_getValue (e);
614 if (multiVal_isInt (m))
616 return (multiVal_forceInt (m) == 0);
624 exprNode_isUnknownConstant (/*@notnull@*/ exprNode e)
626 while (e->kind == XPR_PARENS)
628 e = exprData_getUopNode (e->edata);
629 llassert (exprNode_isDefined (e));
632 if (e->kind == XPR_CONST)
634 multiVal m = exprNode_getValue (e);
636 if (multiVal_isUnknown (m))
646 exprNode_numLiteral (ctype c, /*@temp@*/ cstring t,
647 /*@only@*/ fileloc loc, long val)
649 exprNode e = exprNode_createLoc (c, loc);
651 e->kind = XPR_NUMLIT;
653 llassert (multiVal_isUndefined (e->val));
654 e->val = multiVal_makeInt (val);
655 e->edata = exprData_makeLiteral (cstring_copy (t));
659 e->sref = sRef_makeUnknown ();
660 sRef_setDefNull (e->sref, e->loc);
663 DPRINTF (("Num lit: %s / %s", exprNode_unparse (e), ctype_unparse (exprNode_getType (e))));
668 exprNode_charLiteral (char c, cstring text, /*@only@*/ fileloc loc)
670 exprNode e = exprNode_createLoc (ctype_char, loc);
672 if (context_getFlag (FLG_CHARINTLITERAL))
674 e->typ = ctype_makeConj (ctype_char, ctype_int);
677 e->kind = XPR_NUMLIT;
678 e->val = multiVal_makeChar (c);
680 e->edata = exprData_makeLiteral (cstring_copy (text));
685 exprNode_floatLiteral (double d, ctype ct, cstring text, /*@only@*/ fileloc loc)
687 exprNode e = exprNode_createLoc (ct, loc);
689 e->kind = XPR_NUMLIT;
690 e->val = multiVal_makeDouble (d);
691 e->edata = exprData_makeLiteral (cstring_copy (text));
695 multiVal exprNode_getValue (exprNode e)
697 while (exprNode_isInParens (e)) {
698 if (e->edata != NULL) {
699 e = exprData_getUopNode (e->edata);
705 if (exprNode_isDefined (e)) {
708 return multiVal_undefined;
713 exprNode_stringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
715 exprNode e = exprNode_createLoc (ctype_string, loc);
716 int len = cstring_length (t) - 2;
717 char *ts = cstring_toCharsSafe (t);
718 char *s = cstring_toCharsSafe (cstring_create (len + 1));
720 if (context_getFlag (FLG_STRINGLITERALLEN))
722 if (len > context_getValue (FLG_STRINGLITERALLEN))
724 voptgenerror (FLG_STRINGLITERALLEN,
726 ("String literal length (%d) exceeds maximum "
729 context_getValue (FLG_STRINGLITERALLEN),
735 strncpy (s, ts+1, size_fromInt (len));
739 e->kind = XPR_STRINGLITERAL;
740 e->val = multiVal_makeString (cstring_fromCharsO (s));
741 e->edata = exprData_makeLiteral (t);
742 e->sref = sRef_makeType (ctype_string);
743 /* Start modifications */
744 /* This expr is null terminated, so we set the len and size */
745 sRef_setNullTerminatedState(e->sref);
747 DPRINTF("Len is set to : %d\n\n", strlen((char *)multiVal_forceString(e->val)));
748 DPRINTF("Size is set to : %d\n\n", strlen((char *)multiVal_forceString(e->val)));
749 DPRINTF("State is set to: %d\n\n", e->sref->bufinfo.bufstate);
751 sRef_setLen(e->sref, (int) strlen((char *)multiVal_forceString(e->val)));
752 sRef_setSize(e->sref, (int) strlen((char *)multiVal_forceString(e->val)));
754 if (context_getFlag (FLG_READONLYSTRINGS))
756 sRef_setAliasKind (e->sref, AK_STATIC, fileloc_undefined);
757 sRef_setExKind (e->sref, XO_OBSERVER, loc);
761 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
764 return (e); /* s released */
767 exprNode exprNode_fromUIO (cstring c)
769 fileloc loc = context_getSaveLocation ();
770 exprNode e = exprNode_createPlain (ctype_unknown);
774 if (fileloc_isUndefined (loc))
776 loc = fileloc_copy (g_currentloc);
779 e->loc = loc; /* save loc was mangled */
782 if (usymtab_exists (c))
784 uentry ue = usymtab_lookupEither (c);
786 if (uentry_isDatatype (ue)
787 && uentry_isSpecified (ue))
790 (message ("%q: Specified datatype %s used in code, but not defined. "
791 "(Cannot continue reasonably from this error.)",
792 fileloc_unparse (e->loc), c));
800 llassertprint (!usymtab_exists (c), ("Entry exists: %s", c));
803 ** was supercedeGlobalEntry...is this better?
806 if (!context_inIterEnd ())
808 if (context_inMacro ())
810 if (context_getFlag (FLG_UNRECOG))
814 message ("Unrecognized identifier in macro definition: %s", c), e->loc);
818 flagcode_recordSuppressed (FLG_UNRECOG);
824 (FLG_UNRECOG, message ("Unrecognized identifier: %s", c),
829 e->edata = exprData_makeId (uentry_makeUnrecognized (c, fileloc_copy (loc)));
831 /* No alias errors for unrecognized identifiers */
832 sRef_setAliasKind (e->sref, AK_ERROR, loc);
837 exprNode exprNode_createId (/*@observer@*/ uentry c)
839 if (uentry_isValid (c))
841 exprNode e = exprNode_new ();
843 e->typ = uentry_getType (c);
845 if (uentry_isFunction (c)
846 && !sRef_isLocalVar (uentry_getSref (c)))
848 e->sref = sRef_undefined;
852 e->sref = uentry_getSref (c);
855 if (sRef_isStateUnknown (e->sref) && uentry_isNonLocal (c))
857 sRef_setDefined (e->sref, fileloc_undefined);
861 ** yoikes! leaving this out was a heinous bug...that would have been
862 ** caught if i had lclint working first. gag!
865 e->etext = cstring_undefined;
867 if (uentry_isEitherConstant (c))
870 e->val = multiVal_copy (uentry_getConstantValue (c));
875 e->val = multiVal_unknown ();
878 e->edata = exprData_makeId (c);
879 e->loc = context_getSaveLocation ();
881 if (fileloc_isUndefined (e->loc))
883 fileloc_free (e->loc);
884 e->loc = fileloc_copy (g_currentloc);
887 e->guards = guardSet_new ();
888 e->sets = sRefSet_new ();
889 e->msets = sRefSet_new ();
890 e->uses = sRefSet_new ();
892 /*> missing fields, detected by lclint <*/
893 e->exitCode = XK_NEVERESCAPE;
894 e->isJumpPoint = FALSE;
896 e->mustBreak = FALSE;
898 exprNode_defineConstraints(e);
904 return exprNode_createUnknown ();
908 /*@notnull@*/ exprNode
909 exprNode_fromIdentifier (/*@observer@*/ uentry c)
913 if (context_justPopped ()) /* watch out! c could be dead */
915 uentry ce = usymtab_lookupSafe (LastIdentifier ());
917 if (uentry_isValid (ce))
923 llbuglit ("Looks like Aunt Millie forgot to walk to dog again.");
927 ret = exprNode_fromIdentifierAux (c);
933 static /*@only@*/ /*@notnull@*/ exprNode
934 exprNode_fromIdentifierAux (/*@observer@*/ uentry c)
936 exprNode e = exprNode_createId (c);
939 uentry_setUsed (c, e->loc);
941 if (uentry_isVar (c) && sRef_isGlobal (sr))
943 checkGlobUse (c, FALSE, e);
950 exprNode_isZero (exprNode e)
952 if (exprNode_isDefined (e))
954 multiVal m = exprNode_getValue (e);
956 if (multiVal_isInt (m))
958 return (multiVal_forceInt (m) == 0);
966 exprNode_isNonNegative (exprNode e)
968 if (exprNode_isDefined (e))
970 multiVal m = exprNode_getValue (e);
972 if (multiVal_isInt (m))
974 return (multiVal_forceInt (m) >= 0);
982 ** a[x] - uses a but NOT a[]
983 ** result sref = a[] (set/use in assignment)
985 ** The syntax x[a] is also legal in C, and has the same
986 ** semantics. If ind is an array, and arr is an int, flip
991 exprNode_arrayFetch (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
994 ** error in arr, error propagates (no new messages)
995 ** error in ind, assume valid and continue
998 if (exprNode_isError (e1))
1001 return (exprNode_makeError ());
1007 ctype carr = exprNode_getType (e1);
1008 ctype crarr = ctype_realType (carr);
1011 ** this sets up funny aliasing, that leads to spurious
1012 ** lclint errors. Hence, the i2 comments.
1015 if (!ctype_isRealArray (crarr)
1016 && ctype_isRealNumeric (crarr)
1017 && !exprNode_isError (e2)
1018 && ctype_isRealAP (exprNode_getType (e2))) /* fetch like 3[a] */
1023 carr = exprNode_getType (arr);
1024 crarr = ctype_realType (carr);
1032 if (sRef_possiblyNull (arr->sref))
1034 if (!usymtab_isGuarded (arr->sref))
1036 if (optgenerror (FLG_NULLDEREF,
1037 message ("Index of %s pointer %q: %s",
1038 sRef_nullMessage (arr->sref),
1039 sRef_unparse (arr->sref),
1040 exprNode_unparse (arr)),
1043 sRef_showNullInfo (arr->sref);
1045 /* suppress future messages */
1046 sRef_setNullError (arr->sref);
1051 if (exprNode_isError (ind))
1053 if ((ctype_isArrayPtr (crarr)
1054 && !ctype_isFunction (crarr))
1055 || ctype_isUnknown (carr))
1057 exprNode ret = exprNode_createPartialCopy (arr);
1059 if (ctype_isKnown (carr))
1061 ret->typ = ctype_baseArrayPtr (crarr);
1065 ret->typ = ctype_unknown;
1068 ret->sref = sRef_makeArrayFetch (arr->sref);
1070 ret->kind = XPR_FETCH;
1073 ** Because of funny aliasing (when arr and ind are
1074 ** flipped) spurious errors would be reported here.
1077 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1078 checkSafeUse (ret, arr->sref);
1083 voptgenerror (FLG_TYPE,
1084 message ("Array fetch from non-array (%t): %s[%s]", carr,
1085 exprNode_unparse (e1), exprNode_unparse (e2)),
1087 exprNode_free (arr);
1088 return (exprNode_makeError ());
1093 if (!ctype_isForceRealInt (&(ind->typ)))
1095 ctype rt = ctype_realType (ind->typ);
1097 if (ctype_isChar (rt))
1101 message ("Array fetch using non-integer, %t: %s[%s]",
1103 exprNode_unparse (e1), exprNode_unparse (e2)),
1106 else if (ctype_isEnum (rt))
1110 message ("Array fetch using non-integer, %t: %s[%s]",
1112 exprNode_unparse (e1), exprNode_unparse (e2)),
1119 message ("Array fetch using non-integer, %t: %s[%s]",
1121 exprNode_unparse (e1), exprNode_unparse (e2)),
1125 multiVal_free (ind->val);
1126 ind->val = multiVal_unknown ();
1129 if (ctype_isArrayPtr (crarr) && !ctype_isFunction (crarr))
1131 exprNode ret = exprNode_createSemiCopy (arr);
1132 multiVal m = exprNode_getValue (ind);
1134 ret->typ = ctype_baseArrayPtr (crarr);
1135 ret->kind = XPR_FETCH;
1137 if (multiVal_isInt (m))
1139 int i = (int) multiVal_forceInt (m);
1141 if (sRef_isValid (arr->sref)) {
1142 ret->sref = sRef_makeArrayFetchKnown (arr->sref, i);
1144 ret->sref = sRef_undefined;
1149 ret->sref = sRef_makeArrayFetch (arr->sref);
1152 ret->sets = sRefSet_realNewUnion (arr->sets, ind->sets);
1153 ret->msets = sRefSet_realNewUnion (arr->msets, ind->msets);
1154 ret->uses = sRefSet_realNewUnion (arr->uses, ind->uses);
1156 /* (see comment on spurious errors above) */
1157 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1159 exprNode_checkUse (ret, ind->sref, ind->loc);
1160 exprNode_checkUse (ret, arr->sref, arr->loc);
1166 if (ctype_isUnknown (carr))
1168 exprNode ret = exprNode_createPartialCopy (arr);
1170 ret->kind = XPR_FETCH;
1171 ret->typ = ctype_unknown;
1172 ret->sets = sRefSet_union (ret->sets, ind->sets);
1173 ret->msets = sRefSet_union (ret->msets, ind->msets);
1174 ret->uses = sRefSet_union (ret->uses, ind->uses);
1176 /* (see comment on spurious errors above) */
1177 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1179 exprNode_checkUse (ret, ind->sref, ind->loc);
1180 exprNode_checkUse (ret, arr->sref, arr->loc);
1187 message ("Array fetch from non-array (%t): %s[%s]", carr,
1188 exprNode_unparse (e1), exprNode_unparse (e2)),
1191 exprNode_free (arr);
1192 exprNode_free (ind);
1194 return (exprNode_makeError ());
1204 checkArgs (uentry fcn, /*@dependent@*/ exprNode f, ctype t,
1205 exprNodeList args, exprNode ret)
1207 return (checkArgsReal (fcn, f, ctype_argsFunction (t), args, FALSE, ret));
1211 ** checkPrintfArgs --- checks arguments for printf-like functions
1212 ** Arguments before ... have already been checked.
1213 ** The argument before the ... is a char *.
1214 ** argno is the format string argument.
1218 checkPrintfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1219 exprNodeList args, exprNode ret, int argno)
1222 ** the last argument before the elips is the format string
1227 int nargs = exprNodeList_size (args);
1228 uentryList params = uentry_getParams (fcn);
1232 ** These should be ensured by checkSpecialFunction
1235 llassert (uentryList_size (params) == argno + 1);
1236 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1238 a = exprNodeList_getN (args, argno - 1);
1239 formatloc = fileloc_copy (exprNode_loc (a));
1241 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1242 && exprNode_knownStringValue (a))
1244 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1245 char *code = format;
1248 nargs = exprNodeList_size (args);
1250 while ((code = strchr (code, '%')) != NULL)
1252 char *origcode = code;
1253 char key = *(++code);
1254 ctype modtype = ctype_int;
1255 bool modified = FALSE;
1257 fileloc_addColumn (formatloc, code - ocode);
1260 while (isFlagKey (key))
1263 fileloc_incColumn (formatloc);
1266 if (key == 'm') /* skipped in syslog */
1271 /* ignore field width */
1272 while (isdigit ((int) key) != 0)
1275 fileloc_incColumn (formatloc);
1278 /* ignore precision */
1282 fileloc_incColumn (formatloc);
1285 ** In printf, '*' means: read the next arg as an int for the
1286 ** field width. This seems to be missing from my copy of the
1287 ** standard x3.159-1989. Setion 4.9.6.1 refers to * (described
1288 ** later) but never does.
1293 ; /* don't do anything --- handle later */
1297 while (isdigit ((int) key) != 0)
1300 fileloc_incColumn (formatloc);
1307 modtype = ctype_sint; /* short */
1309 fileloc_incColumn (formatloc);
1311 else if (key == 'l' || key == 'L')
1313 modtype = ctype_lint; /* long */
1315 fileloc_incColumn (formatloc);
1317 if (key == 'l' || key == 'L') {
1318 modtype = ctype_llint; /* long long */
1320 fileloc_incColumn (formatloc);
1328 /* now, key = type of conversion to apply */
1330 fileloc_incColumn (formatloc);
1338 message ("No argument corresponding to %q format "
1339 "code %d (%%%h): \"%s\"",
1340 uentry_getName (fcn),
1342 cstring_fromChars (format)),
1345 if (fileloc_isDefined (formatloc)
1346 && context_getFlag (FLG_SHOWCOL))
1348 llgenindentmsg (cstring_makeLiteral ("Corresponding format code"),
1356 a = exprNodeList_getN (args, i);
1359 if (!exprNode_isError (a))
1365 case '*': /* int argument for fieldwidth */
1366 expecttype = ctype_int;
1367 *(--code) = '%'; /* convert it for next code */
1368 fileloc_subColumn (formatloc, 1);
1369 /*@switchbreak@*/ break;
1372 expecttype = ctype_combine (ctype_uint, modtype);
1373 /*@switchbreak@*/ break;
1375 case 'i': /* int argument */
1377 expecttype = ctype_combine (ctype_int, modtype);
1378 /*@switchbreak@*/ break;
1380 case 'x': /* unsigned int */
1382 expecttype = ctype_combine (ctype_uint, modtype);
1383 /*@switchbreak@*/ break;
1389 case 'f': /* double */
1390 expecttype = ctype_combine (ctype_double, modtype);
1391 /*@switchbreak@*/ break;
1393 case 'c': /* int converted to char (check its a char?) */
1394 expecttype = ctype_makeConj (ctype_char, ctype_uchar);
1395 /*@switchbreak@*/ break;
1397 case 's': /* string */
1398 expecttype = ctype_string;
1399 /*@switchbreak@*/ break;
1402 while (((key = *(++code)) != ']')
1405 fileloc_incColumn (formatloc);
1411 (message ("Bad character set format: %s",
1412 cstring_fromChars (origcode)));
1415 expecttype = ctype_string;
1416 /*@switchbreak@*/ break;
1418 case 'p': /* pointer */
1419 expecttype = ctype_makePointer (ctype_void);
1421 /*@switchbreak@*/ break;
1423 case 'n': /* pointer to int, modified by call! */
1424 expecttype = ctype_combine (ctype_makePointer (ctype_int), modtype);
1426 uentry_setDefState (regArg, SS_ALLOCATED); /* corresponds to out */
1427 /*@switchbreak@*/ break;
1429 case 'm': /* in a syslog, it doesn't consume an argument */
1430 /* should check we're really doing syslog */
1432 /*@switchbreak@*/ break;
1436 expecttype = ctype_unknown;
1440 message ("Unrecognized format code: %s",
1441 cstring_fromChars (origcode)),
1442 fileloc_isDefined (formatloc)
1443 ? formatloc : g_currentloc);
1445 /*@switchbreak@*/ break;
1448 if (!(exprNode_matchArgType (expecttype, a)))
1450 if (ctype_isVoidPointer (expecttype)
1451 && ctype_isRealAbstract (a->typ)
1452 && (context_getFlag (FLG_ABSTVOIDP)))
1458 if (llgenformattypeerror
1459 (expecttype, exprNode_undefined,
1461 message ("Format argument %d to %q (%%%h) expects "
1464 uentry_getName (fcn),
1466 a->typ, exprNode_unparse (a)),
1469 if (fileloc_isDefined (formatloc)
1470 && context_getFlag (FLG_SHOWCOL))
1473 (cstring_makeLiteral
1474 ("Corresponding format code"),
1481 uentry_setType (regArg, expecttype);
1482 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
1484 if (ctype_equal (expecttype, ctype_string))
1486 exprNode_checkUse (a, sRef_makePointer (a->sref), a->loc);
1489 uentry_setType (regArg, ctype_unknown);
1490 uentry_fixupSref (regArg);
1494 exprNode_checkCallModifyVal (a->sref, args, f, ret);
1508 voptgenerror (FLG_TYPE,
1509 message ("Format string for %q has %d arg%p, given %d",
1510 uentry_getName (fcn), i - argno, nargs - argno),
1516 /* no checking possible for compile-time unknown format strings */
1519 fileloc_free (formatloc);
1523 checkScanfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1524 exprNodeList args, exprNode ret, int argno)
1528 int nargs = exprNodeList_size (args);
1529 uentryList params = uentry_getParams (fcn);
1533 ** These should be ensured by checkSpecialFunction
1536 llassert (uentryList_size (params) == argno + 1);
1537 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1539 a = exprNodeList_getN (args, argno - 1);
1540 formatloc = fileloc_copy (exprNode_loc (a));
1542 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1543 && exprNode_knownStringValue (a))
1545 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1546 char *code = format;
1549 nargs = exprNodeList_size (args);
1551 while ((code = strchr (code, '%')) != NULL)
1553 char *origcode = code;
1554 char key = *(++code);
1555 ctype modtype = ctype_int;
1556 char modifier = '\0';
1557 bool modified = TRUE;
1558 bool ignore = FALSE;
1560 fileloc_addColumn (formatloc, code - ocode);
1563 ** this is based on ANSI standard library description of fscanf
1564 ** (from ANSI standard X3.159-1989, 4.9.6.1)
1567 /* '*' suppresses assignment (does not need match argument) */
1574 fileloc_incColumn (formatloc);
1577 /* ignore field width */
1578 while (isdigit ((int) key) != 0)
1581 fileloc_incColumn (formatloc);
1586 modtype = ctype_sint; /* short */
1588 fileloc_incColumn (formatloc);
1590 else if (key == 'l' || key == 'L')
1592 modtype = ctype_lint; /* long */
1596 fileloc_incColumn (formatloc);
1598 if (key == 'l' || key == 'L') {
1599 modtype = ctype_llint; /* long long */
1601 fileloc_incColumn (formatloc);
1609 /* now, key = type of conversion to apply */
1611 fileloc_incColumn (formatloc);
1625 message ("No argument corresponding to %q format "
1626 "code %d (%%%h): \"%s\"",
1627 uentry_getName (fcn),
1629 cstring_fromChars (format)),
1632 if (fileloc_isDefined (formatloc)
1633 && context_getFlag (FLG_SHOWCOL))
1636 (cstring_makeLiteral ("Corresponding format code"),
1644 a = exprNodeList_getN (args, i);
1647 if (!exprNode_isError (a))
1653 case '*': /* int argument for fieldwidth */
1654 expecttype = ctype_makePointer (ctype_int);
1655 *(--code) = '%'; /* convert it for next code */
1656 fileloc_subColumn (formatloc, 1);
1657 /*@switchbreak@*/ break;
1660 expecttype = ctype_makePointer (ctype_combine (ctype_uint, modtype));
1661 /*@switchbreak@*/ break;
1666 case 'X': /* unsigned int */
1667 expecttype = ctype_makePointer (ctype_combine (ctype_int, modtype));
1668 /*@switchbreak@*/ break;
1675 /* printf is double, scanf is float! */
1677 if (modifier == 'l')
1679 expecttype = ctype_makePointer (ctype_double);
1681 else if (modifier == 'L')
1683 expecttype = ctype_makePointer (ctype_ldouble);
1687 llassert (modifier == '\0');
1688 expecttype = ctype_makePointer (ctype_float);
1690 /*@switchbreak@*/ break;
1692 case 'c': /* int converted to char (check its a char?) */
1693 expecttype = ctype_makePointer (ctype_makeConj (ctype_char, ctype_uchar));
1694 /*@switchbreak@*/ break;
1696 case 's': /* string */
1697 expecttype = ctype_string;
1698 /*@switchbreak@*/ break;
1702 while (((key = *(++code)) != ']')
1705 fileloc_incColumn (formatloc);
1711 (message ("Bad character set format: %s",
1712 cstring_fromChars (origcode)));
1715 expecttype = ctype_string;
1716 /*@switchbreak@*/ break;
1718 case 'p': /* pointer */
1719 expecttype = ctype_unknown;
1721 /*@switchbreak@*/ break;
1723 case 'n': /* pointer to int, modified by call! */
1724 expecttype = ctype_makePointer (ctype_int);
1725 /*@switchbreak@*/ break;
1728 expecttype = ctype_unknown;
1732 message ("Unrecognized format code: %s",
1733 cstring_fromChars (origcode)),
1734 fileloc_isDefined (formatloc)
1735 ? formatloc : g_currentloc);
1737 /*@switchbreak@*/ break;
1740 if (!(exprNode_matchArgType (expecttype, a)))
1742 if (ctype_isVoidPointer (expecttype)
1743 && ctype_isRealAbstract (a->typ)
1744 && (context_getFlag (FLG_ABSTVOIDP)))
1750 if (modifier != '\0')
1752 if (llgenformattypeerror
1753 (expecttype, exprNode_undefined,
1755 message ("Format argument %d to %q (%%%h%h) expects "
1758 uentry_getName (fcn),
1761 a->typ, exprNode_unparse (a)),
1764 if (fileloc_isDefined (formatloc)
1765 && context_getFlag (FLG_SHOWCOL))
1768 (cstring_makeLiteral
1769 ("Corresponding format code"),
1777 if (llgenformattypeerror
1778 (expecttype, exprNode_undefined,
1780 message ("Format argument %d to %q (%%%h) expects "
1783 uentry_getName (fcn),
1785 a->typ, exprNode_unparse (a)),
1788 if (fileloc_isDefined (formatloc)
1789 && context_getFlag (FLG_SHOWCOL))
1792 (cstring_makeLiteral
1793 ("Corresponding format code"),
1801 uentry_setType (outArg, expecttype);
1802 checkOneArg (outArg, a, f, FALSE, i+1, nargs);
1803 uentry_setType (outArg, ctype_unknown);
1804 uentry_fixupSref (outArg);
1808 exprNode_checkCallModifyVal (a->sref, args, f, ret);
1813 /* a->sref = defref; */
1823 voptgenerror (FLG_TYPE,
1824 message ("Format string for %q has %d arg%p, given %d",
1825 uentry_getName (fcn), i - argno, nargs - argno),
1831 /* no checking possible for compile-time unknown format strings */
1834 fileloc_free (formatloc);
1838 checkMessageArgs (/*@notnull@*/ /*@dependent@*/ exprNode f,
1841 /*@unused@*/ int argno)
1844 ** the last argument before the elips is the format string
1847 int nargs = exprNodeList_size (args);
1852 a = exprNodeList_getN (args, argno - 1);
1853 formatloc = fileloc_copy (exprNode_loc (a));
1855 if (ctype_isUnknown (cstringType)) {
1856 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
1858 cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
1862 if (ctype_isUnknown (ctypeType)) {
1863 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
1865 ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
1869 if (ctype_isUnknown (filelocType)) {
1870 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
1872 filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
1876 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1877 && exprNode_knownStringValue (a))
1879 cstring format = multiVal_forceString (exprNode_getValue (a));
1880 char *code = cstring_toCharsSafe (format);
1883 nargs = exprNodeList_size (args);
1885 while ((code = strchr (code, '%')) != NULL)
1887 char *origcode = code;
1888 char key = *(++code);
1889 bool isOnly = FALSE;
1891 fileloc_addColumn (formatloc, code - ocode);
1893 while (key >= '0' && key <= '9')
1896 fileloc_incColumn (formatloc);
1900 fileloc_incColumn (formatloc);
1913 message ("Message missing format arg %d (%%%h): \"%s\"",
1914 i + 1, key, format),
1920 a = exprNodeList_getN (args, i);
1924 if (!exprNode_isError (a))
1928 /*@-loopswitchbreak@*/
1934 expecttype = ctype_char; break;
1936 expecttype = cstringType; break;
1938 expecttype = cstringType; isOnly = TRUE; break;
1940 expecttype = cstringType; isOnly = TRUE; break;
1941 case 'd': expecttype = ctype_int; break;
1942 case 'u': expecttype = ctype_uint; break;
1943 case 'w': expecttype = ctype_ulint; break;
1944 case 'f': expecttype = ctype_float; break;
1945 case 'b': expecttype = ctype_bool; break;
1946 case 't': expecttype = ctypeType; break;
1947 case 'l': expecttype = filelocType; break;
1948 case 'p': /* a wee bit of a hack methinks */
1949 expecttype = ctype_int;
1951 case 'r': expecttype = ctype_bool; break;
1953 expecttype = ctype_unknown;
1956 message ("Unrecognized format code: %s",
1957 cstring_fromChars (origcode)),
1958 fileloc_isDefined (formatloc)
1959 ? formatloc : g_currentloc);
1962 /*@=loopswitchbreak@*/
1964 if (!(exprNode_matchArgType (expecttype, a)))
1966 if (ctype_isVoidPointer (expecttype)
1967 && ctype_isRealAbstract (a->typ)
1968 && (context_getFlag (FLG_ABSTVOIDP)))
1974 if (llgenformattypeerror
1975 (expecttype, exprNode_undefined,
1977 message ("Format argument %d to %q (%%%h) expects "
1980 uentry_getName (fcn),
1982 a->typ, exprNode_unparse (a)),
1985 if (fileloc_isDefined (formatloc)
1986 && context_getFlag (FLG_SHOWCOL))
1989 (cstring_makeLiteral
1990 ("Corresponding format code"),
1997 if (ctype_equal (expecttype, cstringType))
2001 checkOneArg (csOnlyArg, a, f, FALSE, i+1, nargs);
2002 uentry_fixupSref (csOnlyArg);
2006 checkOneArg (csArg, a, f, FALSE, i+1, nargs);
2007 uentry_fixupSref (csArg);
2012 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
2013 uentry_fixupSref (regArg);
2022 voptgenerror (FLG_TYPE,
2023 message ("Format string for %q has %d arg%p, given %d",
2024 uentry_getName (fcn), i - argno, nargs -argno),
2030 /* no checking possible for compile-time unknown format strings */
2033 fileloc_free (formatloc);
2037 checkExpressionDefinedAux (/*@notnull@*/ exprNode e1,
2038 /*@notnull@*/ exprNode e2,
2044 bool hadUncon = FALSE;
2046 if (sRef_isGlobal (sRef_getRootBase (e1->sref)) &&
2047 sRefSet_hasUnconstrained (sets2))
2050 (FLG_EVALORDERUNCON,
2052 ("Expression may have undefined behavior (%q used in right operand "
2053 "may set global variable %q used in left operand): %s %s %s",
2054 sRefSet_unparseUnconstrained (sets2),
2055 sRef_unparse (sRef_getRootBase (e1->sref)),
2056 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2060 if (sRef_isGlobal (sRef_getRootBase (e2->sref)) &&
2061 sRefSet_hasUnconstrained (sets1))
2064 (FLG_EVALORDERUNCON,
2066 ("Expression has undefined behavior (%q used in left operand "
2067 "may set global variable %q used in right operand): %s %s %s",
2068 sRefSet_unparseUnconstrained (sets1),
2069 sRef_unparse (e2->sref),
2070 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2074 sRefSet_realElements (e1->uses, sr)
2076 if (sRef_isMeaningful (sr) && sRefSet_member (sets2, sr))
2081 ("Expression has undefined behavior (left operand uses %q, "
2082 "modified by right operand): %s %s %s",
2084 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2087 } end_sRefSet_realElements;
2089 sRefSet_realElements (sets1, sr)
2091 if (sRef_isMeaningful (sr))
2093 if (sRef_same (sr, e2->sref))
2098 ("Expression has undefined behavior (value of right operand "
2099 "modified by left operand): %s %s %s",
2100 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2103 else if (sRefSet_member (e2->uses, sr))
2108 ("Expression has undefined behavior (left operand modifies %q, "
2109 "used by right operand): %s %s %s",
2111 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2116 if (sRefSet_member (sets2, sr))
2118 if (sRef_isUnconstrained (sr))
2126 hadUncon = optgenerror
2127 (FLG_EVALORDERUNCON,
2129 ("Expression may have undefined behavior. Left operand "
2130 "calls %q; right operand calls %q. The unconstrained "
2131 "functions may modify global state used by "
2132 "the other operand): %s %s %s",
2133 sRefSet_unparseUnconstrained (sets1),
2134 sRefSet_unparseUnconstrained (sets2),
2135 exprNode_unparse (e1), lltok_unparse (op),
2136 exprNode_unparse (e2)),
2145 ("Expression has undefined behavior (both "
2146 "operands modify %q): %s %s %s",
2148 exprNode_unparse (e1),
2149 lltok_unparse (op), exprNode_unparse (e2)),
2155 } end_sRefSet_realElements;
2158 static void checkExpressionDefined (exprNode e1, exprNode e2, lltok op)
2160 bool hasError = FALSE;
2162 if (exprNode_isError (e1) || exprNode_isError (e2))
2167 if (sRefSet_member (e2->sets, e1->sref))
2169 if (e2->kind == XPR_CALL)
2175 hasError = optgenerror
2177 message ("Expression has undefined behavior "
2178 "(value of left operand is modified "
2179 "by right operand): %s %s %s",
2180 exprNode_unparse (e1), lltok_unparse (op),
2181 exprNode_unparse (e2)),
2186 if (context_getFlag (FLG_EVALORDERUNCON))
2188 if (sRefSet_member (e2->msets, e1->sref))
2190 if (e2->kind == XPR_CALL)
2196 hasError = optgenerror
2199 ("Expression has undefined behavior (value of left "
2200 "operand may be modified by right operand): %s %s %s",
2201 exprNode_unparse (e1), lltok_unparse (op),
2202 exprNode_unparse (e2)),
2210 checkExpressionDefinedAux (e1, e2, e1->sets, e2->sets, op, FLG_EVALORDER);
2212 if (context_maybeSet (FLG_EVALORDERUNCON))
2214 checkExpressionDefinedAux (e1, e2, e1->msets,
2215 e2->msets, op, FLG_EVALORDERUNCON);
2220 static void checkSequencing (exprNode p_f, exprNodeList p_args);
2223 checkArgsReal (uentry fcn, /*@dependent@*/ exprNode f, uentryList cl,
2224 exprNodeList args, bool isIter, exprNode ret)
2228 if (!exprNode_isError (f))
2230 if (!uentryList_isMissingParams (cl))
2232 int nargs = exprNodeList_size (args);
2233 int expectargs = uentryList_size (cl);
2237 if (expectargs == 0)
2245 message ("Iter %q invoked with %d args, "
2247 uentry_getName (fcn),
2255 message ("Function %s called with %d args, "
2257 exprNode_unparse (f), nargs),
2264 last = uentry_getType (uentryList_getN (cl, expectargs - 1));
2266 exprNodeList_reset (args);
2268 uentryList_elements (cl, current)
2270 ctype ct = uentry_getType (current);
2273 if (ctype_isElips (ct))
2276 ** do special checking for printf/scanf library functions
2278 ** this is kludgey code, just for handling the special case
2282 if (uentry_isPrintfLike (fcn))
2284 checkPrintfArgs (f, fcn, args, ret, i);
2287 else if (uentry_isScanfLike (fcn))
2289 checkScanfArgs (f, fcn, args, ret, i);
2292 else if (uentry_isMessageLike (fcn))
2294 checkMessageArgs (f, fcn, args, i);
2299 llassert (!uentry_isSpecialFunction (fcn));
2302 nargs = expectargs; /* avoid errors */
2307 if (i >= nargs) break;
2309 a = exprNodeList_current (args);
2310 exprNodeList_advance (args);
2314 if (exprNode_isError (a))
2321 probably necessary? I'm not sure about this one
2322 checkMacroParen (a);
2325 f->guards = guardSet_union (f->guards, a->guards);
2327 DPRINTF (("match arg: %s / %s", ctype_unparse (ct), ctype_unparse (a->typ)));
2329 if (!(exprNode_matchArgType (ct, a)))
2331 DPRINTF (("Args mismatch!"));
2333 if (ctype_isVoidPointer (ct)
2334 && (ctype_isPointer (a->typ)
2335 && (ctype_isRealAbstract (ctype_baseArrayPtr (a->typ)))))
2340 ("Pointer to abstract type (%t) used "
2342 "(arg %d to %q): %s",
2344 uentry_getName (fcn),
2345 exprNode_unparse (a)),
2353 (ct, exprNode_undefined,
2356 ("Iter %q expects arg %d to "
2357 "be %t gets %t: %s",
2358 uentry_getName (fcn),
2359 i, ct, a->typ, exprNode_unparse (a)),
2370 ("Function %q expects arg %d to be %t gets %t: %s",
2371 uentry_getName (fcn),
2372 i, ct, a->typ, exprNode_unparse (a)),
2375 DPRINTF (("Types: %s / %s",
2377 ctype_unparse (a->typ)));
2381 ** Clear null marker for abstract types.
2382 ** (It is not revealed, so suppress future messages.)
2385 if (ctype_isAbstract (a->typ))
2387 sRef_setNullUnknown (exprNode_getSref (a), a->loc);
2394 } end_uentryList_elements ;
2397 if (expectargs != nargs) /* note: not != since we may have ... */
2399 if (ctype_isElips (last))
2403 message ("Function %s called with %d args, expects at least %d",
2404 exprNode_unparse (f),
2405 nargs, expectargs - 1),
2414 message ("Iter %q invoked with %d args, expects %d",
2415 uentry_getName (fcn), nargs, expectargs),
2422 message ("Function %s called with %d args, expects %d",
2423 exprNode_unparse (f),
2436 ** Check for undefined code sequences in function arguments:
2438 ** one parameter sets something used by another parameter
2439 ** one parameter sets something set by another parameter
2443 checkSequencingOne (exprNode f, exprNodeList args,
2444 /*@notnull@*/ exprNode el, int argno)
2447 ** Do second loop, iff +undefunspec
2451 int numloops = context_maybeSet (FLG_EVALORDERUNCON) ? 2 : 1;
2453 for (checkloop = 0; checkloop < numloops; checkloop++)
2459 thissets = el->sets;
2463 llassert (checkloop == 1);
2464 thissets = el->msets;
2467 sRefSet_realElements (thissets, thisset)
2471 /*@access exprNodeList@*/
2472 for (j = 0; j < args->nelements; j++)
2474 exprNode jl = args->elements[j];
2475 int thisargno = j + 1;
2477 if (thisargno != argno && exprNode_isDefined (jl))
2479 sRefSet otheruses = jl->uses;
2481 if (sRef_isGlobal (sRef_getRootBase (jl->sref)) &&
2482 sRefSet_hasUnconstrained (thissets))
2485 (FLG_EVALORDERUNCON,
2488 ("%q used in argument %d may set "
2489 "global variable %q used by argument %d: %s(%q)",
2490 cstring_capitalizeFree (sRefSet_unparseUnconstrained (thissets)),
2493 sRef_unparse (sRef_getRootBase (jl->sref)),
2495 exprNode_unparse (f), exprNodeList_unparse (args)),
2499 if (sRefSet_member (otheruses, thisset))
2501 if (sRef_isUnconstrained (thisset))
2504 (FLG_EVALORDERUNCON,
2506 ("Unconstrained functions used in arguments %d (%q) "
2507 "and %d (%s) may modify "
2508 "or use global state in undefined way: %s(%q)",
2510 sRefSet_unparseUnconstrainedPlain (otheruses),
2512 sRef_unconstrainedName (thisset),
2513 exprNode_unparse (f),
2514 exprNodeList_unparse (args)),
2522 ("Argument %d modifies %q, used by argument %d "
2523 "(order of evaluation of actual parameters is "
2524 "undefined): %s(%q)",
2525 argno, sRef_unparse (thisset), thisargno,
2526 exprNode_unparse (f), exprNodeList_unparse (args)),
2532 sRefSet othersets = jl->sets;
2534 if (sRefSet_member (othersets, thisset))
2536 if (sRef_isUnconstrained (thisset))
2539 (FLG_EVALORDERUNCON,
2541 ("Unconstrained functions used in "
2542 "arguments %d (%q) and %d (%s) may modify "
2543 "or use global state in undefined way: %s(%q)",
2545 sRefSet_unparseUnconstrainedPlain (othersets),
2547 sRef_unconstrainedName (thisset),
2548 exprNode_unparse (f), exprNodeList_unparse (args)),
2556 ("Argument %d modifies %q, set by argument %d (order of"
2557 " evaluation of actual parameters is undefined): %s(%q)",
2558 argno, sRef_unparse (thisset), thisargno,
2559 exprNode_unparse (f), exprNodeList_unparse (args)),
2566 /*@noaccess exprNodeList@*/
2567 } end_sRefSet_realElements;
2572 checkSequencing (exprNode f, exprNodeList args)
2574 if (exprNodeList_size (args) > 1)
2579 /*@access exprNodeList*/
2581 for (i = 0; i < args->nelements; i++)
2583 el = args->elements[i];
2585 if (!exprNode_isError (el))
2587 checkSequencingOne (f, args, el, i + 1);
2590 /*@noaccess exprNodeList*/
2595 ** requires le = exprNode_getUentry (f)
2599 checkGlobMods (/*@notnull@*/ /*@dependent@*/ exprNode f,
2600 uentry le, exprNodeList args,
2601 /*@notnull@*/ exprNode ret, int specialArgs)
2603 bool isSpec = FALSE;
2604 bool hasMods = FALSE;
2606 globSet usesGlobs = globSet_undefined;
2607 sRefSet mods = sRefSet_undefined;
2608 bool freshMods = FALSE;
2609 uentryList params = uentryList_undefined;
2612 ** check globals and modifies
2617 if (!uentry_isValid (le))
2619 ctype fr = ctype_realType (f->typ);
2621 if (ctype_isFunction (fr))
2623 params = ctype_argsFunction (fr);
2627 params = uentryList_missingParams;
2630 if (!context_getFlag (FLG_MODNOMODS)
2631 && !context_getFlag (FLG_GLOBUNSPEC))
2633 checkUnspecCall (f, params, args);
2639 fname = uentry_rawName (le);
2643 if (uentry_isFunction (le))
2645 params = uentry_getParams (le);
2646 mods = uentry_getMods (le);
2647 hasMods = uentry_hasMods (le);
2648 usesGlobs = uentry_getGlobs (le);
2649 isSpec = uentry_isSpecified (le);
2651 else /* not a function */
2653 ctype ct = ctype_realType (uentry_getType (le));
2655 llassertprint (uentry_isVar (le) && ctype_isFunction (ct),
2656 ("checkModGlobs: uentry not a function: %s",
2657 uentry_unparse (le)));
2659 params = ctype_argsFunction (ct);
2669 globSet_allElements (usesGlobs, el)
2671 if (sRef_isValid (el))
2673 if (sRef_isInternalState (el) || sRef_isSystemState (el))
2675 context_usedGlobal (el);
2676 exprNode_checkUse (f, el, f->loc);
2678 if (context_checkInternalUse ())
2680 if (!context_globAccess (el))
2682 if (sRef_isSystemState (el)
2683 && !context_getFlag (FLG_MODFILESYSTEM))
2692 ("Called procedure %s may access %q, but "
2693 "globals list does not include globals %s",
2694 exprNode_unparse (f),
2696 cstring_makeLiteralTemp (sRef_isInternalState (el)
2704 else if (sRef_isNothing (el) || sRef_isSpecState (el))
2710 uentry gle = sRef_getUentry (el);
2711 sRef sr = sRef_updateSref (el);
2713 if (sRef_isUndefGlob (el))
2715 sRef_setDefined (sr, f->loc);
2716 exprNode_checkSet (f, sr);
2724 if (sRef_isAllocated (el))
2726 exprNode_checkSet (f, sr);
2730 if (sRef_isStateUndefined (sr))
2735 ("%s %q used by function undefined before call: %s",
2736 sRef_getScopeName (sr),
2738 exprNode_unparse (f)),
2740 sRef_setDefined (sr, f->loc);
2742 exprNode_checkUse (f, sr, f->loc);
2745 checkGlobUse (gle, TRUE, f);
2748 if (sRef_isKilledGlob (el))
2750 sRef_kill (sr, f->loc);
2751 context_usedGlobal (sr);
2755 } end_globSet_allElements;
2761 if (context_hasMods () || context_getFlag (FLG_MODNOMODS))
2763 sRefSet smods = sRefSet_undefined;
2766 ** NEED to check for modifies anything
2770 ** check each sRef that called function modifies (ml), is
2776 sRefSet_allElements (mods, s) /* s is something which may be modified */
2778 if (sRef_isKindSpecial (s))
2780 if (sRef_isSpecInternalState (s))
2782 if (context_getFlag (FLG_MODINTERNALSTRICT))
2784 exprNode_checkCallModifyVal (s, args, f, ret);
2788 sRefSet mmods = context_modList ();
2790 sRefSet_allElements (mmods, el)
2792 if (sRef_isInternalState (el))
2794 sRef_setModified (el);
2796 } end_sRefSet_allElements ;
2801 exprNode_checkCallModifyVal (s, args, f, ret);
2806 sRef rb = sRef_getRootBase (s);
2808 if (sRef_isGlobal (rb))
2810 context_usedGlobal (rb);
2813 if (sRef_isFileStatic (s)
2814 && !fileId_equal (fileloc_fileId (f->loc),
2815 fileloc_fileId (uentry_whereDefined (le))))
2817 smods = sRefSet_insert (smods, s);
2821 exprNode_checkCallModifyVal (s, args, f, ret);
2824 } end_sRefSet_allElements;
2829 ** Static elements in modifies set can have nasty consequences.
2830 ** (I think...have not been able to reproduce a possible bug.)
2833 if (!sRefSet_isDefined (smods))
2835 mods = sRefSet_newCopy (mods);
2838 sRefSet_allElements (smods, el)
2840 bool res = sRefSet_delete (mods, el);
2843 } end_sRefSet_allElements;
2845 sRefSet_free (smods);
2850 else if (sRefSet_isDefined (mods))
2851 { /* just check observers */
2854 sRefSet_allElements (mods, s) /* s is something which may be modified */
2856 sRef rb = sRef_getRootBase (s);
2860 if (sRef_isParam (rb))
2862 sRef b = sRef_fixBaseParam (s, args);
2864 if (sRef_isObserver (b))
2866 exprNode e = exprNodeList_nth (args, sRef_getParam (rb));
2870 message ("Function call may modify observer%q: %s",
2871 sRef_unparsePreOpt (b), exprNode_unparse (e)),
2874 sRef_showExpInfo (b);
2878 } end_sRefSet_allElements;
2882 if (!hasMods) /* no specified modifications */
2884 if (context_getFlag (FLG_MODOBSERVERUNCON))
2886 exprNodeList_elements (args, e)
2888 if (exprNode_isDefined (e))
2890 sRef s = exprNode_getSref (e);
2892 if (sRef_isObserver (s)
2893 && ctype_isMutable (sRef_getType (s)))
2896 (FLG_MODOBSERVERUNCON,
2898 ("Call to unconstrained function %s may modify observer%q: %s",
2899 exprNode_unparse (f),
2900 sRef_unparsePreOpt (s), exprNode_unparse (e)),
2903 sRef_showExpInfo (s);
2907 } end_exprNodeList_elements;
2912 checkAnyCall (f, fname, params, args, hasMods, mods, isSpec, specialArgs);
2914 ret->uses = sRefSet_union (ret->uses, f->uses);
2915 ret->sets = sRefSet_union (ret->sets, f->sets);
2916 ret->msets = sRefSet_union (ret->msets, f->msets);
2921 ** Spurious errors reported, because lclint can't tell
2922 ** mods must be fresh if freshMods is true.
2925 /*@i@*/ sRefSet_free (mods);
2931 void checkGlobUse (uentry glob, bool isCall, /*@notnull@*/ exprNode e)
2933 if (uentry_isVar (glob))
2935 if (context_inFunctionLike ())
2937 sRef sr = uentry_getSref (glob);
2939 context_usedGlobal (sr);
2941 if (context_checkGlobUse (glob))
2943 if (!context_globAccess (sr))
2949 message ("Called procedure %s may access %s %q",
2950 exprNode_unparse (e),
2951 sRef_unparseScope (sr),
2952 uentry_getName (glob)),
2959 message ("Undocumented use of %s %s",
2960 sRef_unparseScope (sr),
2961 exprNode_unparse (e)),
2970 llbug (message ("Global not variable: %q", uentry_unparse (glob)));
2974 static /*@only@*/ exprNode
2975 functionCallSafe (/*@only@*/ /*@notnull@*/ exprNode f,
2976 ctype t, /*@keep@*/ exprNodeList args)
2978 /* requires f is a non-error exprNode, with type function */
2979 cstring fname = exprNode_unparse (f);
2980 uentry le = exprNode_getUentry (f);
2981 exprNode ret = exprNode_createPartialCopy (f);
2986 ret->typ = ctype_returnValue (t);
2987 ret->kind = XPR_CALL;
2989 ret->edata = exprData_makeCall (f, args);
2992 ** Order of these steps is very important!
2994 ** Must check for argument dependencies before messing up uses and sets.
2997 if (context_getFlag (FLG_EVALORDER))
2999 exprNodeList_elements (args, current)
3001 if (exprNode_isDefined (current))
3003 exprNode_addUse (current, current->sref);
3005 } end_exprNodeList_elements;
3007 if (context_maybeSet (FLG_EVALORDER) || context_maybeSet (FLG_EVALORDERUNCON))
3009 checkSequencing (f, args);
3012 exprNodeList_elements (args, current)
3014 if (exprNode_isDefined (current) && sRef_isMeaningful (current->sref))
3016 exprNode_addUse (ret, sRef_makeDerived (current->sref));
3018 } end_exprNodeList_elements ;
3021 special = checkArgs (le, f, t, args, ret);
3022 checkGlobMods (f, le, args, ret, special);
3026 if (uentry_isValid (le)
3027 && (uentry_isFunction (le)
3028 || (uentry_isVariable (le)
3029 && ctype_isFunction (uentry_getType (le)))))
3031 exitkind exk = uentry_getExitCode (le);
3033 /* f->typ is already set to the return type */
3035 ret->sref = uentry_returnedRef (le, args);
3037 if (uentry_isFunction (le) && exprNodeList_size (args) >= 1)
3039 qual nullPred = uentry_nullPred (le);
3041 if (qual_isTrueNull (nullPred))
3043 exprNode arg = exprNodeList_head (args);
3045 if (exprNode_isDefined (arg))
3047 ret->guards = guardSet_addFalseGuard (ret->guards, arg->sref);
3050 else if (qual_isFalseNull (nullPred))
3052 exprNode arg = exprNodeList_head (args);
3054 if (exprNode_isDefined (arg))
3056 ret->guards = guardSet_addTrueGuard (ret->guards, arg->sref);
3061 llassert (qual_isUnknown (nullPred));
3065 if (exitkind_isConditionalExit (exk))
3069 ** if (arg0) then { exit! } else { ; }
3071 ** if (arg0) then { ; } else { exit! }
3076 llassert (!exprNodeList_isEmpty (args));
3077 firstArg = exprNodeList_head (args);
3079 if (exprNode_isDefined (firstArg)
3080 && !guardSet_isEmpty (firstArg->guards))
3082 usymtab_trueBranch (guardSet_undefined);
3083 usymtab_altBranch (guardSet_undefined);
3085 if (exitkind_isTrueExit (exk))
3087 usymtab_popBranches (firstArg,
3088 exprNode_makeMustExit (),
3090 TRUE, TRUEEXITCLAUSE);
3094 usymtab_popBranches (firstArg,
3096 exprNode_makeMustExit (),
3097 TRUE, FALSEEXITCLAUSE);
3101 ret->exitCode = XK_MAYEXIT;
3103 else if (exitkind_mustExit (exk))
3105 ret->exitCode = XK_MUSTEXIT;
3107 else if (exitkind_couldExit (exk))
3109 ret->exitCode = XK_MAYEXIT;
3116 if (cstring_equalLit (fname, "exit"))
3118 if (exprNodeList_size (args) == 1)
3120 exprNode arg = exprNodeList_head (args);
3122 if (exprNode_isDefined (arg) && exprNode_knownIntValue (arg))
3124 long int val = multiVal_forceInt (exprNode_getValue (arg));
3131 ("Argument to exit has implementation defined behavior: %s",
3132 exprNode_unparse (arg)),
3133 exprNode_loc (arg));
3142 exprNode_checkSetAny (ret, uentry_rawName (le));
3149 ** this is yucky! should keep the uentry as part of exprNode!
3152 /*@observer@*/ uentry
3153 exprNode_getUentry (exprNode e)
3155 if (exprNode_isError (e))
3157 return uentry_undefined;
3161 cstring s = exprNode_rootVarName (e);
3162 uentry ue = usymtab_lookupSafe (s);
3169 exprNode_makeInitBlock (lltok brace, /*@only@*/ exprNodeList inits)
3171 exprNode ret = exprNode_createPlain (ctype_unknown);
3173 ret->kind = XPR_INITBLOCK;
3174 ret->edata = exprData_makeCall (exprNode_undefined, inits);
3175 ret->loc = fileloc_update (ret->loc, lltok_getLoc (brace));
3181 exprNode_functionCall (/*@only@*/ exprNode f, /*@only@*/ exprNodeList args)
3187 if (exprNode_isUndefined (f))
3190 exprNodeList_free (args);
3191 return exprNode_undefined;
3194 t = exprNode_getType (f);
3196 if (sRef_isLocalVar (f->sref))
3198 exprNode_checkUse (f, f->sref, f->loc);
3200 if (sRef_possiblyNull (f->sref))
3202 if (!usymtab_isGuarded (f->sref))
3204 if (optgenerror (FLG_NULLDEREF,
3205 message ("Function call using %s pointer %q",
3206 sRef_nullMessage (f->sref),
3207 sRef_unparse (f->sref)),
3210 sRef_showNullInfo (f->sref);
3211 sRef_setNullError (f->sref);
3219 if (ctype_isRealFunction (t))
3221 exprNode ret = functionCallSafe (f, t, args);
3225 else if (ctype_isUnknown (t))
3227 exprNode ret = exprNode_createPartialCopy (f);
3233 exprNodeList_elements (args, current)
3235 if (exprNode_isDefined (current))
3237 exprNode_checkUse (ret, current->sref, ret->loc);
3240 ** also, anything derivable from current->sref may be used
3243 exprNode_addUse (ret, sRef_makeDerived (current->sref));
3244 exprNode_mergeUSs (ret, current);
3246 } end_exprNodeList_elements;
3248 ret->edata = exprData_makeCall (f, args);
3249 ret->kind = XPR_CALL;
3251 tstring = cstring_copy (exprNode_unparse (f));
3253 cstring_markOwned (tstring);
3254 exprNode_checkSetAny (ret, tstring);
3260 voptgenerror (FLG_TYPE,
3261 message ("Call to non-function (type %t): %s", t,
3262 exprNode_unparse (f)),
3265 exprNodeList_free (args);
3267 return (exprNode_makeError ());
3272 exprNode_fieldAccess (/*@only@*/ exprNode s, /*@only@*/ cstring f)
3274 exprNode ret = exprNode_createPartialCopy (s);
3276 ret->kind = XPR_FACCESS;
3278 if (exprNode_isError (s))
3280 ret->edata = exprData_makeField (s, f);
3285 ctype t = exprNode_getType (s);
3286 ctype tr = ctype_realType (t);
3288 checkMacroParen (s);
3290 ret->edata = exprData_makeField (s, f);
3292 if (ctype_isStructorUnion (tr))
3294 uentry tf = uentryList_lookupField (ctype_getFields (tr), f);
3296 if (uentry_isUndefined (tf))
3298 voptgenerror (FLG_TYPE,
3299 message ("Access non-existent field %s of %t: %s", f, t,
3300 exprNode_unparse (ret)),
3307 uentry_setUsed (tf, exprNode_loc (ret));
3309 ret->typ = uentry_getType (tf);
3310 checkSafeUse (ret, s->sref);
3312 ret->sref = sRef_makeField (s->sref, uentry_rawName (tf));
3316 else /* isStructorUnion */
3318 if (ctype_isRealAbstract (tr))
3322 message ("Access field of abstract type (%t): %s.%s",
3323 t, exprNode_unparse (s), f),
3325 ret->typ = ctype_unknown;
3329 if (ctype_isKnown (tr))
3334 ("Access field of non-struct or union (%t): %s.%s",
3335 t, exprNode_unparse (s), f),
3338 ret->typ = ctype_unknown;
3342 cstring sn = cstring_copy (f);
3344 checkSafeUse (ret, s->sref);
3345 cstring_markOwned (sn);
3346 ret->sref = sRef_makeField (s->sref, sn);
3358 exprNode_addParens (/*@only@*/ lltok lpar, /*@only@*/ exprNode e)
3360 exprNode ret = exprNode_createPartialCopy (e);
3362 ret->loc = fileloc_update (ret->loc, lltok_getLoc (lpar));
3363 ret->kind = XPR_PARENS;
3364 ret->edata = exprData_makeUop (e, lpar);
3366 if (!exprNode_isError (e))
3368 ret->exitCode = e->exitCode;
3369 ret->canBreak = e->canBreak;
3370 ret->mustBreak = e->mustBreak;
3371 ret->isJumpPoint = e->isJumpPoint;
3372 ret->sref = e->sref;
3379 exprNode_arrowAccess (/*@only@*/ exprNode s, /*@only@*/ cstring f)
3381 exprNode ret = exprNode_createPartialCopy (s);
3383 ret->edata = exprData_makeField (s, f);
3384 ret->kind = XPR_ARROW;
3386 if (exprNode_isError (s))
3392 ctype t = exprNode_getType (s);
3393 ctype tr = ctype_realType (t);
3395 checkMacroParen (s);
3397 (void) ctype_fixArrayPtr (tr); /* REWRITE THIS */
3399 if (ctype_isRealPointer (tr))
3401 ctype b = ctype_realType (ctype_baseArrayPtr (tr));
3403 if (ctype_isStructorUnion (b))
3405 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
3407 if (sRef_isKnown (s->sref) && sRef_possiblyNull (s->sref))
3409 if (!usymtab_isGuarded (s->sref) && !context_inProtectVars ())
3413 message ("Arrow access from %s pointer%q: %s",
3414 sRef_nullMessage (s->sref),
3415 sRef_unparsePreOpt (s->sref),
3416 exprNode_unparse (ret)),
3419 sRef_showNullInfo (s->sref);
3420 sRef_setNullError (s->sref);
3425 if (uentry_isUndefined (fentry))
3429 message ("Access non-existent field %s of %t: %s",
3430 f, t, exprNode_unparse (ret)),
3432 ret->typ = ctype_unknown;
3439 ** was safeUse: shouldn't be safe!
3442 ** rec must be defined,
3443 ** *rec must be allocated
3444 ** rec->field need only be defined it if is an rvalue
3447 uentry_setUsed (fentry, exprNode_loc (ret));
3448 ret->typ = uentry_getType (fentry);
3450 exprNode_checkUse (ret, s->sref, s->loc);
3452 /* exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc); */
3453 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
3457 else /* Pointer to something that is not a struct or union*/
3459 if (ctype_isRealAbstract (tr))
3461 ctype xrt = ctype_forceRealType (tr);
3465 message ("Arrow access field of abstract type (%t): %s->%s",
3466 t, exprNode_unparse (s), f),
3470 ** Set the state correctly, as if the abstraction is broken.
3473 if (ctype_isRealPointer (xrt) &&
3474 (b = ctype_realType (ctype_baseArrayPtr (xrt)),
3475 ctype_isStructorUnion (b)))
3477 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
3478 ret->typ = uentry_getType (fentry);
3479 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
3483 ret->typ = ctype_unknown;
3484 ret->sref = sRef_undefined;
3487 else /* not a struct, union or abstract */
3489 if (ctype_isUnknown (tr)) {
3490 cstring sn = cstring_copy (f);
3492 DPRINTF (("Here: %s", exprNode_unparse (s)));
3494 exprNode_checkUse (ret, s->sref, s->loc);
3495 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
3497 cstring_markOwned (sn);
3498 ret->sref = sRef_makeArrow (s->sref, sn);
3500 ret->kind = XPR_ARROW;
3505 message ("Arrow access field of non-struct or union "
3506 "pointer (%t): %s->%s",
3507 t, exprNode_unparse (s), f),
3510 ret->typ = ctype_unknown;
3511 ret->sref = sRef_undefined;
3516 else /* its not a pointer */
3518 if (!ctype_isUnknown (tr))
3522 message ("Arrow access of non-pointer (%t): %s->%s",
3523 t, exprNode_unparse (s), f),
3526 ret->typ = ctype_unknown;
3527 ret->sref = sRef_undefined;
3531 cstring sn = cstring_copy (f);
3533 DPRINTF (("Here: %s", exprNode_unparse (s)));
3535 exprNode_checkUse (ret, s->sref, s->loc);
3536 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
3538 cstring_markOwned (sn);
3539 ret->sref = sRef_makeArrow (s->sref, sn);
3541 ret->kind = XPR_ARROW;
3552 ** only postOp's in C: i++ and i--
3556 exprNode_postOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
3558 /* check modification also */
3559 /* cstring opname = lltok_unparse (op);*/
3561 exprNode ret = exprNode_createPartialCopy (e);
3563 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
3564 ret->kind = XPR_POSTOP;
3565 ret->edata = exprData_makeUop (e, op);
3567 if (!exprNode_isDefined (e))
3572 checkMacroParen (e);
3574 exprNode_checkUse (ret, e->sref, e->loc);
3575 exprNode_checkSet (ret, e->sref);
3577 t = exprNode_getType (e);
3579 if (sRef_isUnsafe (e->sref))
3581 voptgenerror (FLG_MACROPARAMS,
3582 message ("Operand of %s is macro parameter (non-functional): %s%s",
3583 lltok_unparse (op), exprNode_unparse (e), lltok_unparse (op)),
3585 sRef_makeSafe (e->sref);
3586 sRef_makeSafe (ret->sref);
3589 if (ctype_isForceRealNumeric (&t) || ctype_isRealAP (t))
3595 if (ctype_isRealAbstract (t))
3599 message ("Operand of %s is abstract type (%t): %s",
3600 lltok_unparse (op), t, exprNode_unparse (e)),
3607 message ("Operand of %s is non-numeric (%t): %s",
3608 lltok_unparse (op), t, exprNode_unparse (e)),
3611 ret->typ = ctype_unknown;
3614 /* if (ctype_isZero (t)) e->typ = ctype_int; */
3616 exprNode_checkModify (e, ret);
3618 /* added 7/11/2000 D.L */
3620 /*DRL 6/8/01 I decided to disable all LCLint Warning here since the code
3621 probably needs a rewrite any way */
3625 // updateEnvironmentForPostOp (e);
3627 /* start modifications */
3628 /* added by Seejo on 4/16/2000 */
3630 /* Arithmetic operations on pointers wil modify the size/len/null terminated
3632 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
3634 ret->sref = sRef_copy (e->sref);
3637 if (lltok_getTok (op) == INC_OP) {
3638 if (sRef_getSize(e->sref) > 0) {
3640 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
3642 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
3643 /* Assumption: there is only 1 \0 in the buffer */
3644 /* This will not be correct if there are 2 \0's in the buffer */
3645 sRef_setNotNullTerminatedState(ret->sref);
3646 sRef_resetLen(ret->sref);
3648 sRef_setNullTerminatedState(ret->sref);
3649 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
3651 if (sRef_isNullTerminated (ret->sref))
3652 printf ("ret->sref is Null Terminated\n");
3653 else if (sRef_isPossiblyNullTerminated (ret->sref))
3654 printf ("ret->sref is Possibly Null Terminated\n");
3655 else if (sRef_isNotNullTerminated (ret->sref))
3656 printf ("ret->sref is Not Null Terminated\n");
3661 if (lltok_getTok (op) == DEC_OP) {
3662 if (sRef_getSize(e->sref) >= 0) {
3663 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
3664 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
3669 /* end modifications */
3675 exprNode_preOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
3677 bool checkMod = FALSE;
3679 int opid = lltok_getTok (op);
3680 exprNode ret = exprNode_createSemiCopy (e);
3682 exprNode_copySets (ret, e);
3684 multiVal_free (ret->val);
3685 ret->val = multiVal_undefined;
3686 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
3687 ret->kind = XPR_PREOP;
3688 ret->edata = exprData_makeUop (e, op);
3690 if (exprNode_isError (e))
3695 checkMacroParen (e);
3697 te = exprNode_getType (e);
3698 tr = ctype_realType (te);
3700 if (opid != TAMPERSAND)
3702 exprNode_checkUse (ret, e->sref, e->loc);
3704 if (ctype_isRealAbstract (tr)
3705 && (!(ctype_isRealBool (te) && (opid == TEXCL))))
3707 if (optgenerror (FLG_ABSTRACT,
3708 message ("Operand of %s is abstract type (%t): %s",
3709 lltok_unparse (op), tr,
3710 exprNode_unparse (ret)),
3713 tr = te = ctype_unknown;
3714 ret->typ = ctype_unknown;
3715 sRef_setNullError (e->sref);
3723 case DEC_OP: /* should also check modification! */
3725 if (sRef_isMacroParamRef (e->sref))
3729 message ("Operand of %s is macro parameter (non-functional): %s",
3730 lltok_unparse (op), exprNode_unparse (ret)),
3735 exprNode_checkSet (ret, e->sref);
3738 if (ctype_isForceRealNumeric (&tr) || ctype_isRealAP (tr))
3743 if (context_msgStrictOps ())
3747 message ("Operand of %s is non-numeric (%t): %s",
3748 lltok_unparse (op), te, exprNode_unparse (ret)),
3751 ret->typ = ctype_int;
3754 /* start modifications */
3755 /* added by Seejo on 4/16/2000 */
3757 /* Arithmetic operations on pointers wil modify the size/len/null terminated
3759 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
3761 ret->sref = sRef_copy (e->sref);
3764 if (lltok_getTok (op) == INC_OP) {
3765 if (sRef_getSize(e->sref) > 0) {
3767 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
3769 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
3770 /* Assumption: there is only 1 \0 in the buffer */
3771 /* This will not be correct if there are 2 \0's in the buffer */
3772 sRef_setNotNullTerminatedState(ret->sref);
3773 sRef_resetLen (ret->sref);
3775 sRef_setNullTerminatedState(ret->sref);
3776 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
3782 if (lltok_getTok (op) == DEC_OP) {
3783 if (sRef_getSize(e->sref) >= 0) {
3784 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
3785 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
3790 /* end modifications */
3797 if (ctype_isForceRealNumeric (&tr))
3801 ret->val = multiVal_invert (exprNode_getValue (e));
3805 ret->val = multiVal_copy (exprNode_getValue (e));
3810 if (context_msgStrictOps ())
3814 message ("Operand of %s is non-numeric (%t): %s",
3815 lltok_unparse (op), te, exprNode_unparse (ret)),
3819 ret->typ = ctype_int;
3823 case TEXCL: /* maybe this should be restricted */
3824 guardSet_flip (ret->guards);
3826 if (ctype_isRealBool (te))
3832 if (ctype_isRealPointer (tr))
3834 if (sRef_isKnown (e->sref))
3836 ret->guards = guardSet_addFalseGuard (ret->guards, e->sref);
3840 (FLG_BOOLOPS, FLG_PTRNEGATE,
3841 message ("Operand of %s is non-boolean (%t): %s",
3842 lltok_unparse (op), te, exprNode_unparse (ret)),
3849 message ("Operand of %s is non-boolean (%t): %s",
3850 lltok_unparse (op), te, exprNode_unparse (ret)),
3854 ret->typ = ctype_bool;
3859 if (ctype_isForceRealInt (&tr))
3864 if (context_msgStrictOps ())
3868 message ("Operand of %s is non-integer (%t): %s",
3869 lltok_unparse (op), te, exprNode_unparse (ret)),
3873 if (ctype_isInt (e->typ))
3879 ret->typ = ctype_int;
3885 ret->typ = ctype_makePointer (e->typ);
3887 if (sRef_isKnown (e->sref))
3889 ret->sref = sRef_makeAddress (e->sref);
3896 if (ctype_isAP (tr))
3898 ret->typ = ctype_baseArrayPtr (e->typ);
3902 if (ctype_isKnown (te))
3904 if (ctype_isFunction (te))
3910 message ("Dereference of function type (%t): %s",
3911 te, exprNode_unparse (ret)),
3916 voptgenerror (FLG_TYPE,
3917 message ("Dereference of non-pointer (%t): %s",
3918 te, exprNode_unparse (ret)),
3920 ret->typ = ctype_unknown;
3925 ret->typ = ctype_unknown;
3930 if (sRef_isKnown (e->sref))
3932 if (sRef_possiblyNull (e->sref))
3934 if (!usymtab_isGuarded (e->sref) && !context_inProtectVars ())
3938 message ("Dereference of %s pointer %q: %s",
3939 sRef_nullMessage (e->sref),
3940 sRef_unparse (e->sref),
3941 exprNode_unparse (ret)),
3944 sRef_showNullInfo (e->sref);
3945 sRef_setNotNull (e->sref, e->loc); /* suppress future messages */
3950 ret->sref = sRef_makePointer (e->sref);
3955 llbug (message ("exprNode_preOp: unhandled op: %s", lltok_unparse (op)));
3960 exprNode_checkModify (e, ret);
3967 ** any reason to disallow sizeof (abstract type) ?
3971 ** used by both sizeof
3975 ctype sizeof_resultType (void)
3977 static ctype sizet = ctype_unknown;
3979 if (ctype_isUnknown (sizet))
3981 if (usymtab_existsType (cstring_makeLiteralTemp ("size_t")))
3983 sizet = uentry_getAbstractType (usymtab_lookup (cstring_makeLiteralTemp ("size_t")));
3987 sizet = ctype_ulint;
3994 exprNode_sizeofType (/*@only@*/ qtype qt)
3996 exprNode ret = exprNode_create (sizeof_resultType ());
3997 ctype ct = qtype_getType (qt);
3999 ret->kind = XPR_SIZEOFT;
4000 ret->edata = exprData_makeSizeofType (qt);
4002 voptgenerror (FLG_SIZEOFTYPE,
4003 message ("Parameter to sizeof is type %s: %s",
4005 exprNode_unparse (ret)),
4012 exprNode_alignofType (/*@only@*/ qtype qt)
4014 exprNode ret = exprNode_create (sizeof_resultType ());
4015 ctype ct = qtype_getType (qt);
4017 ret->kind = XPR_ALIGNOFT;
4018 ret->edata = exprData_makeSizeofType (qt);
4020 voptgenerror (FLG_SIZEOFTYPE,
4021 message ("Parameter to alignof is type %s: %s",
4023 exprNode_unparse (ret)),
4029 exprNode exprNode_offsetof (qtype qt, cstringList s)
4031 exprNode ret = exprNode_create (sizeof_resultType ());
4032 ctype ct = qtype_getType (qt);
4034 ret->kind = XPR_OFFSETOF;
4035 ret->edata = exprData_makeOffsetof (qt, s);
4037 if (!ctype_isRealSU (ct))
4039 voptgenerror (FLG_TYPE,
4040 message ("First parameter to offsetof is not a "
4041 "struct or union type (type %s): %s",
4043 exprNode_unparse (ret)),
4050 cstringList_elements (s, el) {
4054 if (ctype_isUndefined (lt))
4058 else if (!ctype_isRealSU (lt))
4060 voptgenerror (FLG_TYPE,
4061 message ("Inner offsetof type is not a "
4062 "struct or union type (type %s before field %s): %s",
4063 ctype_unparse (lt), el,
4064 exprNode_unparse (ret)),
4070 fields = ctype_getFields (ctype_realType (lt));
4071 fld = uentryList_lookupField (fields, el);
4072 DPRINTF (("Try: %s / %s", ctype_unparse (lt), el));
4074 if (uentry_isUndefined (fld))
4076 if (ctype_equal (lt, ct)) {
4077 voptgenerror (FLG_TYPE,
4078 message ("Field %s in offsetof is not the "
4079 "name of a field of %s: %s",
4082 exprNode_unparse (ret)),
4085 voptgenerror (FLG_TYPE,
4086 message ("Deep field %s in offsetof is not the "
4087 "name of a field of %s: %s",
4090 exprNode_unparse (ret)),
4096 lt = uentry_getType (fld);
4099 } end_cstringList_elements;
4101 /* Should report error if its a bit field - behavior is undefined! */
4108 exprNode_sizeofExpr (/*@only@*/ exprNode e)
4112 if (exprNode_isUndefined (e))
4114 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4115 ret->edata = exprData_makeSingle (e);
4116 ret->typ = sizeof_resultType ();
4117 ret->kind = XPR_SIZEOF;
4121 uentry u = exprNode_getUentry (e);
4123 ret = exprNode_createPartialCopy (e);
4124 ret->edata = exprData_makeSingle (e);
4126 ret->typ = sizeof_resultType ();
4127 ret->kind = XPR_SIZEOF;
4129 if (uentry_isValid (u)
4130 && uentry_isRefParam (u)
4131 && ctype_isRealArray (uentry_getType (u)))
4134 (FLG_SIZEOFFORMALARRAY,
4135 message ("Parameter to sizeof is an array-type function parameter: %s",
4136 exprNode_unparse (ret)),
4142 ** sizeof (x) doesn't "really" use x
4149 exprNode_alignofExpr (/*@only@*/ exprNode e)
4153 if (exprNode_isUndefined (e))
4155 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4159 ret = exprNode_createPartialCopy (e);
4162 ret->edata = exprData_makeSingle (e);
4163 ret->typ = sizeof_resultType ();
4164 ret->kind = XPR_ALIGNOF;
4167 ** sizeof (x) doesn't "really" use x
4174 exprNode_cast (/*@only@*/ lltok tok, /*@only@*/ exprNode e, /*@only@*/ qtype q)
4180 if (exprNode_isError (e))
4183 lltok_release (tok);
4184 return exprNode_undefined;
4187 checkMacroParen (e);
4189 c = qtype_getType (q);
4190 t = exprNode_getType (e);
4192 ret = exprNode_createPartialCopy (e);
4194 ret->loc = fileloc_update (ret->loc, lltok_getLoc (tok));
4196 ret->kind = XPR_CAST;
4197 ret->edata = exprData_makeCast (tok, e, q);
4199 if (ctype_isRealSU (ctype_getBaseType (sRef_getType (e->sref))))
4202 ** This is a bit of a hack to avoid a problem
4203 ** when the code does,
4204 ** (some other struct) x
4209 ret->sref = sRef_copy (e->sref);
4210 usymtab_addForceMustAlias (ret->sref, e->sref);
4211 sRef_setTypeFull (ret->sref, c);
4212 DPRINTF (("Cast: %s -> %s", sRef_unparseFull (e->sref),
4213 sRef_unparseFull (ret->sref)));
4217 ret->sref = e->sref;
4218 sRef_setTypeFull (ret->sref, c);
4219 DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref)));
4226 ** void * <-> abstract * (if FLG_ABSTVOIDP)
4227 ** abstract * <-> void * (if FLG_ABSTVOIDP)
4230 if (ctype_isVoid (c)) /* cast to void is always okay --- discard value */
4234 else if (ctype_isRealAP (c)) /* casting to array or pointer */
4236 ctype bc = ctype_getBaseType (c);
4237 ctype bt = ctype_getBaseType (t);
4238 ctype rt = ctype_realType (t);
4240 if (ctype_isFunction (ctype_baseArrayPtr (ctype_realType (c)))
4241 && (ctype_isArrayPtr (rt)
4242 && !ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
4246 message ("Cast from function pointer type (%t) to "
4247 "non-function pointer (%t): %s",
4248 c, t, exprNode_unparse (ret)),
4252 if (!ctype_isFunction (ctype_baseArrayPtr (c))
4253 && (ctype_isArrayPtr (rt)
4254 && ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
4258 message ("Cast from non-function pointer type (%t) to "
4259 "function pointer (%t): %s",
4260 c, t, exprNode_unparse (ret)),
4264 if (exprNode_isZero (e) && context_getFlag (FLG_ZEROPTR) &&
4265 !(ctype_isRealAbstract (bc)
4266 && context_hasAccess (ctype_typeId (bc))))
4268 ; /* okay to cast zero */
4272 if (ctype_isRealAbstract (bc)
4273 && !context_hasAccess (ctype_typeId (bc)))
4275 if (ctype_isVoidPointer (t) || ctype_isUnknown (t))
4279 message ("Cast to underlying abstract type %t: %s",
4280 c, exprNode_unparse (ret)),
4287 message ("Cast to underlying abstract type %t: %s",
4288 c, exprNode_unparse (ret)),
4293 if (ctype_isRealAbstract (bt)
4294 && !context_hasAccess (ctype_typeId (bt)))
4296 if (ctype_isUnknown (c) || ctype_isVoidPointer (c))
4300 message ("Cast from underlying abstract type %t: %s",
4301 t, exprNode_unparse (ret)),
4308 message ("Cast from underlying abstract type %t: %s",
4309 t, exprNode_unparse (ret)),
4317 ctype bt = ctype_realType (ctype_getBaseType (t));
4318 ctype bc = ctype_realType (ctype_getBaseType (c));
4320 if (ctype_isAbstract (bt) && !context_hasAccess (ctype_typeId (bt)))
4322 if (ctype_match (c, t))
4324 if (ctype_equal (c, t))
4328 message ("Redundant cast involving abstract type %t: %s",
4329 bt, exprNode_unparse (ret)),
4337 message ("Cast from abstract type %t: %s",
4338 bt, exprNode_unparse (ret)),
4343 if (ctype_isAbstract (bc)
4344 && !context_hasAccess (ctype_typeId (bc)))
4346 if (ctype_match (c, t))
4354 message ("Cast to abstract type %t: %s", bc,
4355 exprNode_unparse (ret)),
4361 if (ctype_isAbstract (c))
4363 if (sRef_isExposed (e->sref) || sRef_isOnly (e->sref))
4365 /* okay, cast exposed to abstract */
4366 sRef_clearExKindComplete (ret->sref, fileloc_undefined);
4370 if (ctype_isVisiblySharable (t)
4371 && sRef_isExternallyVisible (e->sref)
4372 && !(ctype_isAbstract (t)
4373 && context_hasAccess (ctype_typeId (t))))
4377 message ("Cast to abstract type from externally visible "
4378 "mutable storage exposes rep of %s: %s",
4380 exprNode_unparse (e)),
4390 evaluationOrderUndefined (lltok op)
4392 int opid = lltok_getTok (op);
4394 return (opid != AND_OP && opid != OR_OP);
4397 static bool checkIntegral (/*@notnull@*/ exprNode e1,
4398 /*@notnull@*/ exprNode e2,
4399 /*@notnull@*/ exprNode ret,
4404 ctype te1 = exprNode_getType (e1);
4405 ctype te2 = exprNode_getType (e2);
4407 ctype tr1 = ctype_realishType (te1);
4408 ctype tr2 = ctype_realishType (te2);
4410 if (ctype_isForceRealInt (&tr1) && ctype_isForceRealInt (&tr2))
4416 if (context_msgStrictOps ())
4418 if (!ctype_isInt (tr1) && !ctype_isInt (tr2))
4420 if (ctype_sameName (te1, te2))
4424 message ("Operands of %s are non-integer (%t): %s",
4425 lltok_unparse (op), te1,
4426 exprNode_unparse (ret)),
4433 message ("Operands of %s are non-integers (%t, %t): %s",
4434 lltok_unparse (op), te1, te2,
4435 exprNode_unparse (ret)),
4439 else if (!ctype_isInt (tr1))
4443 message ("Left operand of %s is non-integer (%t): %s",
4444 lltok_unparse (op), te1, exprNode_unparse (ret)),
4448 /* !ctype_isInt (te2) */
4452 message ("Right operand of %s is non-integer (%t): %s",
4453 lltok_unparse (op), te2, exprNode_unparse (ret)),
4463 ** returns exprNode representing e1 op e2
4465 ** uses msg if there are errors
4466 ** can be used for both assignment ops and regular ops
4471 static /*@only@*/ /*@notnull@*/ exprNode
4472 exprNode_makeOp (/*@keep@*/ exprNode e1, /*@keep@*/ exprNode e2,
4473 /*@keep@*/ lltok op)
4475 ctype te1, te2, tr1, tr2, tret;
4476 int opid = lltok_getTok (op);
4477 bool hasError = FALSE;
4480 if (exprNode_isError (e1))
4482 ret = exprNode_createPartialNVCopy (e2);
4486 ret = exprNode_createPartialNVCopy (e1);
4489 ret->val = multiVal_undefined;
4491 ret->edata = exprData_makeOp (e1, e2, op);
4493 if (exprNode_isError (e1) || exprNode_isError (e2))
4495 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
4496 || opid == EQ_OP || opid == NE_OP
4497 || opid == AND_OP || opid == OR_OP)
4499 ret->typ = ctype_bool;
4502 if (exprNode_isDefined (e1))
4504 exprNode_checkUse (ret, e1->sref, e1->loc);
4507 if (exprNode_isDefined (e2))
4509 exprNode_mergeUSs (ret, e2);
4510 exprNode_checkUse (ret, e2->sref, e2->loc);
4516 tret = ctype_unknown;
4517 te1 = exprNode_getType (e1);
4518 DPRINTF (("te1 = %s / %s", exprNode_unparse (e1), ctype_unparse (te1)));
4520 te2 = exprNode_getType (e2);
4522 tr1 = ctype_realishType (te1);
4523 tr2 = ctype_realishType (te2);
4527 ret->guards = guardSet_or (ret->guards, e2->guards);
4529 else if (opid == AND_OP)
4531 ret->guards = guardSet_and (ret->guards, e2->guards);
4538 if (opid == EQ_OP || opid == NE_OP)
4540 exprNode temp1 = e1, temp2 = e2;
4542 /* could do NULL == x */
4544 if (exprNode_isNullValue (e1) || exprNode_isUnknownConstant (e1))
4546 temp1 = e2; temp2 = e1;
4549 if (exprNode_isNullValue (temp2) || exprNode_isUnknownConstant (temp2))
4551 reflectNullTest (temp1, (opid == NE_OP));
4552 guardSet_free (ret->guards);
4553 ret->guards = guardSet_copy (temp1->guards);
4557 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
4558 || opid == EQ_OP || opid == NE_OP || opid == AND_OP || opid == OR_OP)
4563 if (anyAbstract (tr1, tr2) &&
4564 (!((ctype_isRealBool (te1) || ctype_isRealBool (te2)) &&
4565 (opid == AND_OP || opid == OR_OP
4566 || opid == EQ_OP || opid == NE_OP))))
4568 abstractOpError (tr1, tr2, op, e1, e2, e1->loc, e2->loc);
4570 else if (ctype_isUnknown (te1) || ctype_isUnknown (te2))
4572 /* unknown types, no comparisons possible */
4578 case TMULT: /* multiplication and division: */
4580 case MUL_ASSIGN: /* numeric, numeric -> numeric */
4581 case DIV_ASSIGN: /* */
4583 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
4586 case TPLUS: /* addition and subtraction: */
4587 case TMINUS: /* pointer, int -> pointer */
4588 case SUB_ASSIGN: /* int, pointer -> pointer */
4589 case ADD_ASSIGN: /* numeric, numeric -> numeric */
4591 tr1 = ctype_fixArrayPtr (tr1);
4593 if ((ctype_isRealPointer (tr1) && !exprNode_isNullValue (e1))
4594 && (!ctype_isRealPointer (tr2) && ctype_isRealInt (tr2)))
4598 if (context_msgPointerArith ())
4602 message ("Pointer arithmetic (%t, %t): %s",
4603 te1, te2, exprNode_unparse (ret)),
4607 if (sRef_possiblyNull (e1->sref)
4608 && !usymtab_isGuarded (e1->sref))
4611 (FLG_NULLPOINTERARITH,
4612 message ("Pointer arithmetic involving possibly "
4613 "null pointer %s: %s",
4614 exprNode_unparse (e1),
4615 exprNode_unparse (ret)),
4619 ret->sref = sRef_copy (e1->sref);
4621 /* start modifications */
4622 /* added by Seejo on 4/16/2000 */
4624 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4626 if ((sRef_isPossiblyNullTerminated (e1->sref)) || (sRef_isNullTerminated(e1->sref))) {
4627 //if (sRef_isKnown (e->sref)) {
4628 //ret->sref = sRef_makeAddress (e->sref);
4633 added ugly fixed to stop
4634 program from crashing on point + int +int
4635 one day I'll fix this or ask Seejo wtf the codes supposed to do. */
4637 if (!multiVal_isInt (e2->val) )
4641 val = (int) multiVal_forceInt (e2->val);
4643 /* Operator : + or += */
4644 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
4645 if (sRef_getSize(e1->sref) >= val) {/* Incrementing the pointer by
4646 val should not result in a
4647 size < 0 (size = 0 is ok !) */
4649 sRef_setSize (ret->sref, sRef_getSize(e1->sref) - val);
4651 if (sRef_getLen(e1->sref) == val) { /* i.e. the character at posn val is \0 */
4652 sRef_setNotNullTerminatedState(ret->sref);
4653 sRef_resetLen (ret->sref);
4655 sRef_setNullTerminatedState(ret->sref);
4656 sRef_setLen (ret->sref, sRef_getLen(e1->sref) - val);
4661 /* Operator : - or -= */
4662 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
4663 if (sRef_getSize(e1->sref) >= 0) {
4664 sRef_setSize (ret->sref, sRef_getSize(e1->sref) + val);
4665 sRef_setLen (ret->sref, sRef_getLen(e1->sref) + val);
4670 /* end modifications */
4672 sRef_setNullError (ret->sref);
4675 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
4676 ** since is points to storage that should not be deallocated
4677 ** through this pointer.
4680 if (sRef_isOnly (ret->sref)
4681 || sRef_isFresh (ret->sref))
4683 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
4688 else if ((!ctype_isRealPointer(tr1) && ctype_isRealInt (tr1))
4689 && (ctype_isRealPointer (tr2) && !exprNode_isNullValue (e2)))
4691 if (context_msgPointerArith ())
4695 message ("Pointer arithmetic (%t, %t): %s",
4696 te1, te2, exprNode_unparse (ret)),
4700 if (sRef_possiblyNull (e1->sref)
4701 && !usymtab_isGuarded (e1->sref))
4704 (FLG_NULLPOINTERARITH,
4705 message ("Pointer arithmetic involving possibly "
4706 "null pointer %s: %s",
4707 exprNode_unparse (e2),
4708 exprNode_unparse (ret)),
4712 ret->sref = sRef_copy (e2->sref);
4714 /* start modifications */
4715 /* added by Seejo on 4/16/2000 */
4717 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4720 if ((sRef_isPossiblyNullTerminated (e2->sref)) || (sRef_isNullTerminated(e2->sref))) {
4721 //if (sRef_isKnown (e->sref)) {
4722 //ret->sref = sRef_makeAddress (e->sref);
4725 int val = (int) multiVal_forceInt (e1->val);
4727 /* Operator : + or += */
4728 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
4729 if (sRef_getSize(e2->sref) >= val) {/* Incrementing the pointer by
4730 val should not result in a
4731 size < 0 (size = 0 is ok !) */
4733 sRef_setSize (ret->sref, sRef_getSize(e2->sref) - val);
4735 if (sRef_getLen(e2->sref) == val) { /* i.e. the character at posn val is \0 */
4736 sRef_setNotNullTerminatedState(ret->sref);
4737 sRef_resetLen (ret->sref);
4739 sRef_setNullTerminatedState(ret->sref);
4740 sRef_setLen (ret->sref, sRef_getLen(e2->sref) - val);
4745 /* Operator : - or -= */
4746 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
4747 if (sRef_getSize(e2->sref) >= 0) {
4748 sRef_setSize (ret->sref, sRef_getSize(e2->sref) + val);
4749 sRef_setLen (ret->sref, sRef_getLen(e2->sref) + val);
4754 /* end modifications */
4756 sRef_setNullError (ret->sref);
4759 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
4760 ** since is points to storage that should not be deallocated
4761 ** through this pointer.
4764 if (sRef_isOnly (ret->sref)
4765 || sRef_isFresh (ret->sref)) {
4766 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
4770 ret->sref = e2->sref;
4774 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
4779 case LEFT_ASSIGN: /* Shifts: should be unsigned values */
4783 case TAMPERSAND: /* bitwise & */
4785 case TCIRC: /* ^ (XOR) */
4790 bool reported = FALSE;
4791 flagcode code = FLG_BITWISEOPS;
4793 if (opid == LEFT_OP || opid == LEFT_ASSIGN
4794 || opid == RIGHT_OP || opid == RIGHT_ASSIGN) {
4795 code = FLG_SHIFTSIGNED;
4798 if (!ctype_isUnsigned (tr1))
4800 if (exprNode_isNonNegative (e1)) {
4803 reported = optgenerror
4805 message ("Left operand of %s is not unsigned value (%t): %s",
4806 lltok_unparse (op), te1,
4807 exprNode_unparse (ret)),
4817 /* right need not be signed for shifts */
4818 if (code != FLG_SHIFTSIGNED
4819 && !ctype_isUnsigned (tr2))
4821 if (!exprNode_isNonNegative (e2)) {
4822 reported = optgenerror
4824 message ("Right operand of %s is not unsigned value (%t): %s",
4825 lltok_unparse (op), te2,
4826 exprNode_unparse (ret)),
4834 if (!checkIntegral (e1, e2, ret, op)) {
4835 te1 = ctype_unknown;
4839 DPRINTF (("Set: %s", ctype_unparse (te1)));
4842 ** tret is the widest type of te1 and te2
4845 tret = ctype_widest (te1, te2);
4850 if (checkIntegral (e1, e2, ret, op)) {
4853 tret = ctype_unknown;
4858 case TLT: /* comparisons */
4859 case TGT: /* numeric, numeric -> bool */
4860 if ((ctype_isReal (tr1) && !ctype_isInt (tr1))
4861 || (ctype_isReal (tr2) && !ctype_isInt (tr2)))
4864 bool fepsilon = FALSE;
4866 if (!ctype_isReal (rtype) || ctype_isInt (rtype))
4871 if (opid == TLT || opid == TGT)
4873 uentry ue1 = exprNode_getUentry (e1);
4874 uentry ue2 = exprNode_getUentry (e2);
4877 ** FLT_EPSILON, etc. really is a variable, not
4881 if (uentry_isVariable (ue1))
4883 cstring uname = uentry_rawName (ue1);
4885 if (cstring_equalLit (uname, "FLT_EPSILON")
4886 || cstring_equalLit (uname, "DBL_EPSILON")
4887 || cstring_equalLit (uname, "LDBL_EPSILON"))
4893 if (uentry_isVariable (ue2))
4895 cstring uname = uentry_rawName (ue2);
4897 if (cstring_equalLit (uname, "FLT_EPSILON")
4898 || cstring_equalLit (uname, "DBL_EPSILON")
4899 || cstring_equalLit (uname, "LDBL_EPSILON"))
4908 ; /* Don't complain. */
4914 message ("Dangerous comparison involving %s types: %s",
4915 ctype_unparse (rtype),
4916 exprNode_unparse (ret)),
4925 ** Types should match.
4928 if (!exprNode_matchTypes (e1, e2))
4930 hasError = gentypeerror
4932 message ("Operands of %s have incompatible types (%t, %t): %s",
4933 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
4939 || (ctype_isForceRealNumeric (&tr1)
4940 && ctype_isForceRealNumeric (&tr2)) ||
4941 (ctype_isRealPointer (tr1) && ctype_isRealPointer (tr2)))
4947 if ((ctype_isRealNumeric (tr1) && ctype_isRealPointer (tr2)) ||
4948 (ctype_isRealPointer (tr1) && ctype_isRealNumeric (tr2)))
4952 message ("Comparison of pointer and numeric (%t, %t): %s",
4953 te1, te2, exprNode_unparse (ret)),
4958 (void) checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
4963 /* EQ_OP should NOT be used with booleans (unless one is FALSE) */
4965 if ((opid == EQ_OP || opid == NE_OP) &&
4966 ctype_isDirectBool (tr1) && ctype_isDirectBool (tr2))
4969 ** is one a variable?
4972 if (uentry_isVariable (exprNode_getUentry (e1))
4973 || uentry_isVariable (exprNode_getUentry (e2)))
4976 ** comparisons with FALSE are okay
4979 if (exprNode_isFalseConstant (e1)
4980 || exprNode_isFalseConstant (e2))
4989 ("Use of %q with %s variables (risks inconsistency because "
4990 "of multiple true values): %s",
4991 cstring_makeLiteral ((opid == EQ_OP) ? "==" : "!="),
4992 context_printBoolName (), exprNode_unparse (ret)),
4999 case AND_OP: /* bool, bool -> bool */
5002 if (ctype_isForceRealBool (&tr1) && ctype_isForceRealBool (&tr2))
5008 if (context_maybeSet (FLG_BOOLOPS))
5010 if (!ctype_isRealBool (te1) && !ctype_isRealBool (te2))
5012 if (ctype_sameName (te1, te2))
5016 message ("Operands of %s are non-boolean (%t): %s",
5017 lltok_unparse (op), te1,
5018 exprNode_unparse (ret)),
5026 ("Operands of %s are non-booleans (%t, %t): %s",
5027 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5031 else if (!ctype_isRealBool (te1))
5035 message ("Left operand of %s is non-boolean (%t): %s",
5036 lltok_unparse (op), te1, exprNode_unparse (ret)),
5039 else if (!ctype_isRealBool (te2))
5043 message ("Right operand of %s is non-boolean (%t): %s",
5044 lltok_unparse (op), te2, exprNode_unparse (ret)),
5057 (cstring_makeLiteral
5058 ("There has been a problem in the parser. This is due to a bug "
5059 "in either lclint, bison or gcc version 2.95 optimizations, "
5060 "but it has not been confirmed. Please try rebuidling LCLint "
5061 "without the -O<n> option."));
5066 DPRINTF (("Return type: %s", ctype_unparse (tret)));
5069 exprNode_checkUse (ret, e1->sref, e1->loc);
5070 exprNode_mergeUSs (ret, e2);
5071 exprNode_checkUse (ret, e2->sref, e2->loc);
5077 exprNode_op (/*@only@*/ exprNode e1, /*@keep@*/ exprNode e2,
5078 /*@only@*/ lltok op)
5082 checkMacroParen (e1);
5083 checkMacroParen (e2);
5085 if (evaluationOrderUndefined (op) && context_maybeSet (FLG_EVALORDER))
5087 checkExpressionDefined (e1, e2, op);
5090 ret = exprNode_makeOp (e1, e2, op);
5095 void exprNode_checkAssignMod (exprNode e1, exprNode ret)
5098 ** This is somewhat bogus!
5100 ** Assigning to a nested observer in a non-observer datatype
5101 ** should not produce an error.
5104 sRef ref = exprNode_getSref (e1);
5106 DPRINTF (("Check assign mod: %s",
5107 sRef_unparseFull (ref)));
5109 if (sRef_isObserver (ref)
5110 || ((sRef_isFileStatic (ref) || sRef_isGlobal (ref))
5111 && ctype_isArray (ctype_realType (sRef_getType (ref)))))
5113 sRef base = sRef_getBase (ref);
5115 if (sRef_isValid (base) && sRef_isObserver (base))
5117 exprNode_checkModify (e1, ret);
5121 exprNode_checkModifyVal (e1, ret);
5126 exprNode_checkModify (e1, ret);
5131 exprNode_assign (/*@only@*/ exprNode e1,
5132 /*@only@*/ exprNode e2, /*@only@*/ lltok op)
5134 bool isalloc = FALSE;
5135 bool isjustalloc = FALSE;
5138 DPRINTF (("%s [%s] <- %s [%s]",
5139 exprNode_unparse (e1),
5140 ctype_unparse (e1->typ),
5141 exprNode_unparse (e2),
5142 ctype_unparse (e2->typ)));
5144 if (lltok_getTok (op) != TASSIGN)
5146 ret = exprNode_makeOp (e1, e2, op);
5150 ret = exprNode_createPartialCopy (e1);
5151 ret->kind = XPR_ASSIGN;
5152 ret->edata = exprData_makeOp (e1, e2, op);
5154 if (!exprNode_isError (e2))
5156 ret->sets = sRefSet_union (ret->sets, e2->sets);
5157 ret->msets = sRefSet_union (ret->msets, e2->msets);
5158 ret->uses = sRefSet_union (ret->uses, e2->uses);
5162 checkExpressionDefined (e1, e2, op);
5164 if (exprNode_isError (e1))
5166 if (!exprNode_isError (e2))
5168 ret->loc = fileloc_update (ret->loc, e2->loc);
5172 ret->loc = fileloc_update (ret->loc, g_currentloc);
5176 if (!exprNode_isError (e2))
5178 checkMacroParen (e2);
5181 if (exprNode_isDefined (e1))
5183 if (sRef_isMacroParamRef (e1->sref))
5185 if (context_inIterDef ())
5187 uentry ue = sRef_getUentry (e1->sref);
5189 if (uentry_isYield (ue))
5195 if (fileloc_isDefined (e1->loc))
5199 message ("Assignment to non-yield iter parameter: %q",
5200 sRef_unparse (e1->sref)),
5207 message ("Assignment to non-yield iter parameter: %q",
5208 sRef_unparse (e1->sref)),
5215 if (fileloc_isDefined (e1->loc))
5219 message ("Assignment to macro parameter: %q",
5220 sRef_unparse (e1->sref)),
5227 message ("Assignment to macro parameter: %q",
5228 sRef_unparse (e1->sref)),
5235 exprNode_checkAssignMod (e1, ret);
5238 if (exprNode_isDefined (e2))
5240 if (lltok_getTok (op) == TASSIGN)
5242 ctype te1 = exprNode_getType (e1);
5243 ctype te2 = exprNode_getType (e2);
5245 if (!ctype_forceMatch (te1, te2))
5247 if (exprNode_matchLiteral (te1, e2))
5255 message ("Assignment of %t to %t: %s %s %s",
5256 te2, te1, exprNode_unparse (e1),
5258 exprNode_unparse (e2)),
5264 exprNode_mergeUSs (ret, e2);
5265 exprNode_checkUse (ret, e2->sref, e2->loc);
5267 doAssign (e1, e2, FALSE);
5268 ret->sref = e1->sref;
5272 if (exprNode_isDefined (e2))
5274 exprNode_mergeUSs (ret, e2);
5275 exprNode_checkUse (ret, e2->sref, e2->loc);
5279 if (sRef_isPointer (e1->sref) && !sRef_isMacroParamRef (e1->sref))
5281 exprNode_checkUse (ret, sRef_getBase (e1->sref), e1->loc);
5284 isjustalloc = sRef_isJustAllocated (e1->sref);
5285 isalloc = sRef_isAllocated (e1->sref);
5287 if (sRef_isField (e1->sref))
5289 sRef root = sRef_getRootBase (sRef_getBase (e1->sref));
5291 if (!sRef_isAllocated (root) && !sRef_isMacroParamRef (root))
5293 exprNode_checkUse (ret, root, e1->loc);
5299 ** be careful! this defines e1->sref.
5302 if (!sRef_isMacroParamRef (e1->sref))
5304 exprNode_checkSet (ret, e1->sref);
5309 sRef_setAllocatedComplete (e1->sref, exprNode_isDefined (e2)
5310 ? e2->loc : e1->loc);
5316 sRef_setAllocatedShallowComplete (e1->sref, exprNode_loc (e2));
5325 exprNode_cond (/*@keep@*/ exprNode pred, /*@keep@*/ exprNode ifclause,
5326 /*@keep@*/ exprNode elseclause)
5330 if (!exprNode_isError (pred))
5332 ret = exprNode_createPartialCopy (pred);
5333 checkMacroParen (pred);
5334 exprNode_checkPred (cstring_makeLiteralTemp ("conditional"), pred);
5336 if (!exprNode_isError (ifclause))
5338 checkMacroParen (ifclause); /* update macro counts! */
5340 if (!exprNode_isError (elseclause))
5342 checkMacroParen (elseclause);
5344 if (!exprNode_matchTypes (ifclause, elseclause))
5347 (exprNode_getType (ifclause),
5349 exprNode_getType (elseclause),
5351 message ("Conditional clauses are not of same type: "
5353 exprNode_unparse (ifclause),
5354 exprNode_getType (ifclause),
5355 exprNode_unparse (elseclause),
5356 exprNode_getType (elseclause)),
5359 ret->sref = sRef_undefined;
5360 ret->typ = ctype_unknown;
5365 /* for now...should merge the states */
5366 ret->sref = ifclause->sref;
5367 ret->typ = ifclause->typ;
5369 if (exprNode_isNullValue (ifclause))
5371 ret->typ = elseclause->typ;
5375 exprNode_checkUse (ret, pred->sref, pred->loc);
5376 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
5377 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
5379 exprNode_mergeCondUSs (ret, ifclause, elseclause);
5384 ret->typ = ifclause->typ;
5386 exprNode_checkUse (pred, pred->sref, pred->loc);
5387 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
5389 exprNode_mergeCondUSs (ret, ifclause, exprNode_undefined);
5394 if (!exprNode_isError (elseclause))
5396 ret->typ = elseclause->typ;
5398 exprNode_checkUse (pred, pred->sref, pred->loc);
5399 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
5401 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
5405 else /* pred is error */
5407 if (!exprNode_isError (ifclause))
5409 ret = exprNode_createSemiCopy (ifclause);
5411 checkMacroParen (ifclause); /* update macro counts! */
5413 if (!exprNode_isError (elseclause))
5415 checkMacroParen (elseclause);
5417 ret->typ = ifclause->typ;
5419 if (!ctype_forceMatch (ifclause->typ, elseclause->typ))
5422 (exprNode_getType (ifclause),
5424 exprNode_getType (elseclause),
5426 message ("Conditional clauses are not of same type: "
5428 exprNode_unparse (ifclause),
5429 exprNode_getType (ifclause),
5430 exprNode_unparse (elseclause),
5431 exprNode_getType (elseclause)),
5434 ret->typ = ctype_unknown;
5438 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
5439 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
5441 exprNode_mergeCondUSs (ret, ifclause, elseclause);
5444 else if (!exprNode_isError (elseclause)) /* pred, if errors */
5446 ret = exprNode_createSemiCopy (ifclause);
5448 ret->typ = elseclause->typ;
5449 checkMacroParen (elseclause);
5451 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
5452 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
5454 else /* all errors! */
5456 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
5460 ret->kind = XPR_COND;
5461 ret->edata = exprData_makeCond (pred, ifclause, elseclause);
5463 if (exprNode_isDefined (ifclause) && exprNode_isDefined (elseclause))
5465 exprNode_combineControl (ret, ifclause, elseclause);
5472 exprNode_vaArg (/*@only@*/ lltok tok, /*@only@*/ exprNode arg, /*@only@*/ qtype qt)
5474 ctype totype = qtype_getType (qt);
5476 exprNode_createPartialLocCopy (arg, fileloc_copy (lltok_getLoc (tok)));
5480 ** check use of va_arg : <valist>, type -> type
5483 if (exprNode_isError (arg))
5488 targ = exprNode_getType (arg);
5491 ** arg should have be a pointer
5494 if (!ctype_isUA (targ) ||
5495 (!usymId_equal (ctype_typeId (targ),
5496 usymtab_getTypeId (cstring_makeLiteralTemp ("va_list")))))
5500 message ("First argument to va_arg is not a va_list (type %t): %s",
5501 targ, exprNode_unparse (arg)),
5505 exprNode_checkSet (ret, arg->sref);
5509 ** return type is totype
5513 ret->kind = XPR_VAARG;
5514 ret->edata = exprData_makeCast (tok, arg, qt);
5519 exprNode exprNode_labelMarker (/*@only@*/ cstring label)
5521 exprNode ret = exprNode_createPlain (ctype_undefined);
5522 ret->kind = XPR_LABEL;
5523 ret->edata = exprData_makeLiteral (label);
5524 ret->isJumpPoint = TRUE;
5526 return (ret); /* for now, ignore label */
5529 exprNode exprNode_notReached (/*@returned@*/ exprNode stmt)
5531 if (exprNode_isDefined (stmt))
5533 stmt->isJumpPoint = TRUE;
5535 /* This prevent stray no return path errors, etc. */
5536 stmt->exitCode = XK_MUSTEXIT;
5542 bool exprNode_isDefaultMarker (exprNode e)
5544 if (exprNode_isDefined (e))
5546 return (e->kind == XPR_DEFAULT || e->kind == XPR_FTDEFAULT);
5552 bool exprNode_isCaseMarker (exprNode e)
5554 if (exprNode_isDefined (e))
5556 return (e->kind == XPR_FTCASE || e->kind == XPR_CASE);
5562 bool exprNode_isLabelMarker (exprNode e)
5564 if (exprNode_isDefined (e))
5566 return (e->kind == XPR_LABEL);
5572 exprNode exprNode_caseMarker (/*@only@*/ exprNode test, bool fallThrough)
5574 exprNode ret = exprNode_createPartialCopy (test);
5576 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
5578 if (exprNode_isError (test)) {
5582 exprNode_checkUse (ret, test->sref, test->loc);
5584 usymtab_setExitCode (ret->exitCode);
5588 usymtab_setMustBreak ();
5591 ret->edata = exprData_makeSingle (test);
5592 ret->isJumpPoint = TRUE;
5598 exprNode exprNode_caseStatement (/*@only@*/ exprNode test, /*@only@*/ exprNode stmt, bool fallThrough)
5600 exprNode ret = exprNode_createPartialCopy (test);
5602 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
5603 ret->edata = exprData_makePair (test, stmt);
5604 ret->isJumpPoint = TRUE;
5606 if (exprNode_isError (test))
5611 exprNode_checkUse (ret, test->sref, test->loc);
5613 if (exprNode_isError (stmt))
5618 exprNode_mergeUSs (ret, stmt);
5620 ret->exitCode = stmt->exitCode;
5621 ret->mustBreak = stmt->mustBreak;
5622 ret->canBreak = stmt->canBreak;
5624 usymtab_setExitCode (ret->exitCode);
5628 usymtab_setMustBreak ();
5635 /*@notnull@*/ /*@only@*/ exprNode
5636 exprNode_defaultMarker (/*@only@*/ lltok def, bool fallThrough)
5638 exprNode ret = exprNode_createTok (def);
5640 ret->isJumpPoint = TRUE;
5641 ret->kind = fallThrough ? XPR_FTDEFAULT : XPR_DEFAULT;
5646 exprNode_mayEscape (exprNode e)
5648 if (exprNode_isDefined (e))
5650 return exitkind_couldEscape (e->exitCode);
5656 exprNode_mustBreak (exprNode e)
5658 if (exprNode_isDefined (e))
5660 return e->mustBreak;
5666 exprNode_mustEscape (exprNode e)
5668 if (exprNode_isDefined (e))
5670 return exitkind_mustEscape (e->exitCode) || exprNode_mustBreak (e);
5677 exprNode_errorEscape (exprNode e)
5679 if (exprNode_isDefined (e))
5681 return exitkind_isError (e->exitCode);
5687 exprNode exprNode_concat (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
5689 exprNode ret = exprNode_createPartialCopy (e1);
5691 ret->edata = exprData_makePair (e1, e2);
5692 ret->kind = XPR_STMTLIST;
5694 if (exprNode_isDefined (e1))
5696 ret->isJumpPoint = e1->isJumpPoint;
5697 ret->canBreak = e1->canBreak;
5701 if (exprNode_isDefined (e2))
5703 ret->loc = fileloc_update (ret->loc, e2->loc);
5707 if (exprNode_isDefined (e2))
5709 ret->exitCode = e2->exitCode;
5710 ret->mustBreak = e2->mustBreak;
5711 if (e2->canBreak) ret->canBreak = TRUE;
5715 ** if e1 must return, then e2 is unreachable!
5718 if (exprNode_isDefined (e1) && exprNode_isDefined (e2))
5720 if ((exprNode_mustEscape (e1) || exprNode_mustBreak (e1))
5721 && !(e2->isJumpPoint))
5723 if (context_getFlag (FLG_UNREACHABLE))
5727 if (e2->kind == XPR_STMT)
5729 nr = exprData_getUopNode (e2->edata);
5732 if ((nr->kind == XPR_TOK
5733 && lltok_isSemi (exprData_getTok (nr->edata))))
5735 /* okay to have unreachable ";" */
5736 ret->exitCode = XK_MUSTEXIT;
5737 ret->canBreak = TRUE;
5741 if (optgenerror (FLG_UNREACHABLE,
5742 message ("Unreachable code: %s",
5743 exprNode_unparseFirst (nr)),
5746 ret->isJumpPoint = TRUE;
5747 ret->mustBreak = FALSE;
5748 ret->exitCode = XK_ERROR;
5749 DPRINTF (("Jump point: %s", exprNode_unparse (ret)));
5753 ret->exitCode = XK_MUSTEXIT;
5754 ret->canBreak = TRUE;
5762 if ((e2->kind == XPR_CASE || e2->kind == XPR_DEFAULT))
5765 ** We want a warning anytime we have:
5767 ** yyy; <<<- no break or return
5771 exprNode lastStmt = exprNode_lastStatement (e1);
5773 if (exprNode_isDefined (lastStmt)
5774 && !exprNode_mustEscape (lastStmt)
5775 && !exprNode_mustBreak (lastStmt)
5776 && !exprNode_isCaseMarker (lastStmt)
5777 && !exprNode_isDefaultMarker (lastStmt)
5778 && !exprNode_isLabelMarker (lastStmt))
5780 voptgenerror (FLG_CASEBREAK,
5782 ("Fall through case (no preceeding break)"),
5789 exprNode_mergeUSs (ret, e2);
5790 // ret = exprNode_mergeEnvironments (ret, e1, e2);
5791 usymtab_setExitCode (ret->exitCode);
5795 usymtab_setMustBreak ();
5801 exprNode exprNode_createTok (/*@only@*/ lltok t)
5803 exprNode ret = exprNode_create (ctype_unknown);
5804 ret->kind = XPR_TOK;
5805 ret->edata = exprData_makeTok (t);
5809 exprNode exprNode_statement (/*@only@*/ exprNode e, /*@only@*/ lltok t)
5811 if (!exprNode_isError (e))
5813 exprNode_checkStatement(e);
5816 return (exprNode_statementError (e, t));
5819 static exprNode exprNode_statementError (/*@only@*/ exprNode e, /*@only@*/ lltok t)
5821 exprNode ret = exprNode_createPartialCopy (e);
5823 if (!exprNode_isError (e))
5825 if (e->kind != XPR_ASSIGN)
5827 exprNode_checkUse (ret, e->sref, e->loc);
5830 ret->exitCode = e->exitCode;
5831 ret->canBreak = e->canBreak;
5832 ret->mustBreak = e->mustBreak;
5835 ret->edata = exprData_makeUop (e, t);
5836 ret->kind = XPR_STMT;
5841 exprNode exprNode_checkExpr (/*@returned@*/ exprNode e)
5843 if (!exprNode_isError (e))
5845 if (e->kind != XPR_ASSIGN)
5847 exprNode_checkUse (e, e->sref, e->loc);
5854 void exprNode_produceGuards (exprNode pred)
5856 if (!exprNode_isError (pred))
5858 if (ctype_isRealPointer (pred->typ))
5860 pred->guards = guardSet_addTrueGuard (pred->guards, pred->sref);
5863 exprNode_checkUse (pred, pred->sref, pred->loc);
5864 exprNode_resetSref (pred);
5868 exprNode exprNode_makeBlock (/*@only@*/ exprNode e)
5870 exprNode ret = exprNode_createPartialCopy (e);
5872 if (!exprNode_isError (e))
5874 ret->exitCode = e->exitCode;
5875 ret->canBreak = e->canBreak;
5876 ret->mustBreak = e->mustBreak;
5879 ret->edata = exprData_makeSingle (e);
5880 ret->kind = XPR_BLOCK;
5884 bool exprNode_isBlock (exprNode e)
5886 return (exprNode_isDefined (e)
5887 && ((e)->kind == XPR_BLOCK));
5890 bool exprNode_isAssign (exprNode e)
5892 if (exprNode_isDefined (e))
5894 return (e->kind == XPR_ASSIGN);
5900 bool exprNode_isEmptyStatement (exprNode e)
5902 return (exprNode_isDefined (e)
5903 && (e->kind == XPR_TOK)
5904 && (lltok_isSemi (exprData_getTok (e->edata))));
5907 exprNode exprNode_if (/*@only@*/ exprNode pred, /*@only@*/ exprNode tclause)
5910 bool emptyErr = FALSE;
5912 if (context_maybeSet (FLG_IFEMPTY))
5914 if (exprNode_isEmptyStatement (tclause))
5916 emptyErr = optgenerror (FLG_IFEMPTY,
5918 ("Body of if statement is empty"),
5919 exprNode_loc (tclause));
5923 if (!emptyErr && context_maybeSet (FLG_IFBLOCK))
5925 if (exprNode_isDefined (tclause)
5926 && !exprNode_isBlock (tclause))
5928 voptgenerror (FLG_IFBLOCK,
5930 ("Body of if statement is not a block: %s",
5931 exprNode_unparse (tclause)),
5932 exprNode_loc (tclause));
5936 if (exprNode_isError (pred))
5938 if (exprNode_isError (tclause))
5940 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
5944 ret = exprNode_createPartialCopy (tclause);
5949 if (exprNode_mustEscape (pred))
5953 message ("Predicate always exits: %s", exprNode_unparse (pred)),
5954 exprNode_loc (pred));
5957 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
5958 exprNode_checkUse (pred, pred->sref, pred->loc);
5960 if (!exprNode_isError (tclause))
5962 exprNode_mergeCondUSs (pred, tclause, exprNode_undefined);
5965 ret = exprNode_createPartialCopy (pred);
5969 ret->edata = exprData_makePair (pred, tclause);
5971 ret->exitCode = XK_UNKNOWN;
5973 if (exprNode_isDefined (tclause))
5975 ret->exitCode = exitkind_makeConditional (tclause->exitCode);
5976 ret->canBreak = tclause->canBreak;
5977 ret->sets = sRefSet_union (ret->sets, tclause->sets);
5978 ret->msets = sRefSet_union (ret->msets, tclause->msets);
5979 ret->uses = sRefSet_union (ret->uses, tclause->uses);
5982 ret->mustBreak = FALSE;
5987 exprNode exprNode_ifelse (/*@only@*/ exprNode pred,
5988 /*@only@*/ exprNode tclause,
5989 /*@only@*/ exprNode eclause)
5992 bool tEmptyErr = FALSE;
5993 bool eEmptyErr = FALSE;
5995 if (context_maybeSet (FLG_IFEMPTY))
5997 if (exprNode_isEmptyStatement (tclause))
5999 tEmptyErr = optgenerror
6002 ("Body of if clause of if statement is empty"),
6003 exprNode_loc (tclause));
6006 if (exprNode_isEmptyStatement (eclause))
6008 eEmptyErr = optgenerror
6011 ("Body of else clause of if statement is empty"),
6012 exprNode_loc (eclause));
6016 if (context_maybeSet (FLG_IFBLOCK))
6019 && exprNode_isDefined (tclause)
6020 && !exprNode_isBlock (tclause))
6022 voptgenerror (FLG_IFBLOCK,
6024 ("Body of if clause of if statement is not a block: %s",
6025 exprNode_unparse (tclause)),
6026 exprNode_loc (tclause));
6030 && exprNode_isDefined (eclause)
6031 && !exprNode_isBlock (eclause)
6032 && !(eclause->kind == XPR_IF)
6033 && !(eclause->kind == XPR_IFELSE))
6038 ("Body of else clause of if statement is not a block: %s",
6039 exprNode_unparse (eclause)),
6040 exprNode_loc (eclause));
6044 if (context_maybeSet (FLG_ELSEIFCOMPLETE))
6046 if (exprNode_isDefined (eclause)
6047 && (eclause->kind == XPR_IF))
6049 voptgenerror (FLG_ELSEIFCOMPLETE,
6050 message ("Incomplete else if logic (no final else): %s",
6051 exprNode_unparse (eclause)),
6052 exprNode_loc (eclause));
6056 if (exprNode_isError (pred))
6058 if (exprNode_isError (tclause))
6060 if (exprNode_isError (eclause))
6062 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
6066 ret = exprNode_createPartialCopy (eclause);
6071 ret = exprNode_createPartialCopy (tclause);
6074 else /* pred is okay */
6076 ret = exprNode_createPartialCopy (pred);
6078 if (exprNode_mustEscape (pred))
6082 message ("Predicate always exits: %s", exprNode_unparse (pred)),
6083 exprNode_loc (pred));
6086 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
6087 exprNode_checkUse (ret, pred->sref, pred->loc);
6089 exprNode_mergeCondUSs (ret, tclause, eclause);
6092 ret->kind = XPR_IFELSE;
6093 ret->edata = exprData_makeCond (pred, tclause, eclause);
6095 if (exprNode_isDefined (tclause) && exprNode_isDefined (eclause))
6097 exprNode_combineControl (ret, tclause, eclause);
6098 ret->loc = fileloc_update (ret->loc, eclause->loc);
6105 ** *allpaths <- TRUE iff all executions paths must go through the switch
6109 checkSwitchExpr (exprNode test, /*@dependent@*/ exprNode e, /*@out@*/ bool *allpaths)
6111 exprNodeSList el = exprNode_flatten (e);
6112 bool mustReturn = TRUE; /* find a branch that doesn't */
6113 bool thisReturn = FALSE;
6114 bool hasDefault = FALSE;
6115 bool hasAllMembers = FALSE;
6116 bool inSwitch = FALSE;
6117 bool isEnumSwitch = FALSE;
6118 bool canBreak = FALSE;
6119 bool fallThrough = FALSE;
6120 ctype ct = ctype_unknown;
6121 enumNameSList usedEnums;
6124 if (exprNode_isDefined (test))
6129 ttype = ctype_realType (ct);
6131 if (ctype_isEnum (ttype))
6133 isEnumSwitch = TRUE;
6134 enums = ctype_elist (ttype);
6135 usedEnums = enumNameSList_new ();
6139 exprNodeSList_elements (el, current)
6141 if (exprNode_isDefined (current))
6143 switch (current->kind)
6151 message ("Duplicate default cases in switch"),
6152 exprNode_loc (current));
6157 if (current->kind == XPR_DEFAULT || current->kind == XPR_FTDEFAULT)
6165 exprNode st = exprData_getSingle (current->edata);
6166 uentry ue = exprNode_getUentry (st);
6168 if (uentry_isValid (ue))
6170 cstring cname = uentry_rawName (ue);
6172 if (enumNameList_member (/*@-usedef@*/enums/*@=usedef@*/, cname))
6174 if (enumNameSList_member
6175 (/*@-usedef@*/usedEnums/*@=usedef@*/, cname))
6179 message ("Duplicate case in switch: %s",
6185 enumNameSList_addh (usedEnums, cname);
6192 message ("Case in switch not %s member: %s",
6193 ctype_unparse (ct), cname),
6200 if (inSwitch && !fallThrough)
6202 if (!thisReturn || canBreak)
6212 /*@switchbreak@*/ break;
6214 thisReturn = thisReturn || exprNode_mustEscape (current);
6215 canBreak = canBreak || current->canBreak;
6216 if (canBreak) fallThrough = FALSE;
6219 } end_exprNodeSList_elements;
6221 if (inSwitch) /* check the last one! */
6223 if (!thisReturn || canBreak)
6232 && (enumNameSList_size (/*@-usedef@*/usedEnums/*@=usedef@*/) !=
6233 enumNameList_size (/*@-usedef@*/enums/*@=usedef@*/)))
6235 enumNameSList unused = enumNameSList_subtract (enums, usedEnums);
6237 voptgenerror (FLG_MISSCASE,
6238 message ("Missing case%s in switch: %q",
6239 cstring_makeLiteralTemp
6240 ((enumNameSList_size (unused) > 1) ? "s" : ""),
6241 enumNameSList_unparse (unused)),
6244 enumNameSList_free (unused);
6248 hasAllMembers = TRUE;
6252 enumNameSList_free (usedEnums);
6256 *allpaths = hasDefault;
6259 exprNodeSList_free (el);
6260 return ((hasDefault || hasAllMembers) && mustReturn);
6263 exprNode exprNode_switch (/*@only@*/ exprNode e, /*@only@*/ exprNode s)
6265 exprNode ret = exprNode_createPartialCopy (e);
6268 DPRINTF (("Switch: %s", exprNode_unparse (s)));
6270 ret->kind = XPR_SWITCH;
6271 ret->edata = exprData_makePair (e, s);
6273 if (!exprNode_isError (s))
6275 exprNode fs = exprNode_firstStatement (s);
6276 ret->loc = fileloc_update (ret->loc, s->loc);
6278 if (exprNode_isUndefined (fs)
6279 || exprNode_isCaseMarker (fs) || exprNode_isLabelMarker (fs)
6280 || exprNode_isDefaultMarker (fs)) {
6283 voptgenerror (FLG_FIRSTCASE,
6285 ("Statement after switch is not a case: %s", exprNode_unparse (fs)),
6290 if (!exprNode_isError (e))
6292 if (checkSwitchExpr (e, s, &allpaths))
6294 ret->exitCode = XK_MUSTRETURN;
6298 ret->exitCode = e->exitCode;
6301 ret->canBreak = e->canBreak;
6302 ret->mustBreak = e->mustBreak;
6306 ** exprNode.c:3883,32: Variable allpaths used before definition
6313 DPRINTF (("Context exit switch!"));
6314 context_exitSwitch (ret, allpaths);
6315 DPRINTF (("Context exit switch done!"));
6320 static void checkInfiniteLoop (/*@notnull@*/ exprNode test,
6321 /*@notnull@*/ exprNode body)
6323 sRefSet tuses = test->uses;
6325 if (!sRefSet_isEmpty (test->uses))
6327 sRefSet sets = sRefSet_newCopy (body->sets);
6328 bool hasError = TRUE;
6329 bool innerState = FALSE;
6330 sRefSet tuncon = sRefSet_undefined;
6332 sets = sRefSet_union (sets, test->sets);
6333 sets = sRefSet_union (sets, body->msets);
6334 sets = sRefSet_union (sets, test->msets);
6336 sRefSet_allElements (tuses, el)
6338 if (sRef_isUnconstrained (el))
6340 tuncon = sRefSet_insert (tuncon, el);
6344 if (sRefSet_member (sets, el))
6351 if (sRef_isInternalState (el)
6352 || sRef_isFileStatic (sRef_getRootBase (el)))
6356 } end_sRefSet_allElements ;
6360 sRefSet suncon = sRefSet_undefined;
6361 bool sinner = FALSE;
6363 sRefSet_allElements (sets, el)
6365 if (sRef_isUnconstrained (el))
6367 suncon = sRefSet_insert (suncon, el);
6369 else if (sRef_isInternalState (el))
6377 } end_sRefSet_allElements ;
6379 if (sinner && innerState)
6383 else if (sRefSet_isEmpty (tuncon)
6384 && sRefSet_isEmpty (suncon))
6389 ("Suspected infinite loop. No value used in loop test (%q) "
6390 "is modified by test or loop body.",
6391 sRefSet_unparsePlain (tuses)),
6396 if (sRefSet_isEmpty (tuncon))
6400 message ("Suspected infinite loop. No condition values "
6401 "modified. Modification possible through "
6402 "unconstrained calls: %q",
6403 sRefSet_unparsePlain (suncon)),
6410 message ("Suspected infinite loop. No condition values "
6411 "modified. Possible undetected dependency through "
6412 "unconstrained calls in loop test: %q",
6413 sRefSet_unparsePlain (tuncon)),
6419 sRefSet_free (sets);
6423 exprNode exprNode_while (/*@keep@*/ exprNode t, /*@keep@*/ exprNode b)
6426 bool emptyErr = FALSE;
6428 if (context_maybeSet (FLG_WHILEEMPTY))
6430 if (exprNode_isEmptyStatement (b))
6432 emptyErr = optgenerror
6435 ("Body of while statement is empty"),
6440 if (!emptyErr && context_maybeSet (FLG_WHILEBLOCK))
6442 if (exprNode_isDefined (b)
6443 && !exprNode_isBlock (b))
6445 if (context_inIterDef ()
6446 && (b->kind == XPR_STMTLIST
6447 || b->kind == XPR_TOK))
6453 voptgenerror (FLG_WHILEBLOCK,
6455 ("Body of while statement is not a block: %s",
6456 exprNode_unparse (b)),
6462 if (exprNode_isError (t))
6464 if (exprNode_isError (b))
6466 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
6470 ret = exprNode_createPartialCopy (b);
6477 ret = exprNode_createPartialCopy (t);
6479 llassert (t->kind == XPR_WHILEPRED);
6481 test = exprData_getSingle (t->edata);
6483 if (!exprNode_isError (b) && exprNode_isDefined (test))
6485 if (context_maybeSet (FLG_INFLOOPS)
6486 || context_maybeSet (FLG_INFLOOPSUNCON))
6489 ** check that some variable in the predicate is set by the body
6490 ** if the predicate uses any variables
6493 checkInfiniteLoop (test, b);
6496 exprNode_mergeUSs (ret, b);
6498 if (exprNode_isDefined (b))
6500 ret->exitCode = exitkind_makeConditional (b->exitCode);
6505 ret->edata = exprData_makePair (t, b);
6506 ret->kind = XPR_WHILE;
6508 if (exprNode_isDefined (t) && exprNode_mustEscape (t))
6512 message ("Predicate always exits: %s", exprNode_unparse (t)),
6516 ret->exitCode = XK_NEVERESCAPE;
6519 ** If loop is infinite, and there is no break inside,
6520 ** exit code is never reach.
6523 if (exprNode_knownIntValue (t))
6525 if (!exprNode_isZero (t))
6527 if (exprNode_isDefined (b))
6531 /* Really, it means never reached. */
6532 ret->exitCode = XK_MUSTEXIT;
6542 ret->canBreak = FALSE;
6543 ret->mustBreak = FALSE;
6549 ** do { b } while (t);
6551 ** note: body passed as first argument
6554 exprNode exprNode_doWhile (/*@only@*/ exprNode b, /*@only@*/ exprNode t)
6558 if (exprNode_isError (t))
6560 if (exprNode_isError (b))
6562 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
6566 ret = exprNode_createPartialCopy (b);
6568 ret->exitCode = exitkind_makeConditional (b->exitCode);
6569 exprNode_checkUse (ret, b->sref, b->loc);
6570 ret->exitCode = b->exitCode;
6571 ret->canBreak = b->canBreak;
6572 ret->mustBreak = b->mustBreak;
6577 ret = exprNode_createPartialCopy (t);
6578 exprNode_checkPred (cstring_makeLiteralTemp ("while"), t);
6580 if (!exprNode_isError (b))
6583 ** forgot the copy's --- why wasn't this detected??
6586 ret->sets = sRefSet_copy (ret->sets, b->sets);
6587 ret->msets = sRefSet_copy (ret->msets, b->msets);
6588 ret->uses = sRefSet_copy (ret->uses, b->uses);
6590 /* left this out --- causes and aliasing bug (infinite loop)
6591 should be detected?? */
6593 exprNode_checkUse (ret, b->sref, b->loc);
6594 exprNode_mergeUSs (ret, t);
6595 exprNode_checkUse (ret, t->sref, t->loc);
6597 ret->exitCode = b->exitCode;
6598 ret->canBreak = b->canBreak;
6599 ret->mustBreak = b->mustBreak;
6603 context_exitDoWhileClause (t);
6605 ret->kind = XPR_DOWHILE;
6606 ret->edata = exprData_makePair (t, b);
6610 exprNode exprNode_for (/*@keep@*/ exprNode inc, /*@keep@*/ exprNode body)
6613 bool emptyErr = FALSE;
6615 if (context_maybeSet (FLG_FOREMPTY))
6617 if (exprNode_isEmptyStatement (body))
6619 emptyErr = optgenerror
6622 ("Body of for statement is empty"),
6623 exprNode_loc (body));
6627 if (!emptyErr && context_maybeSet (FLG_FORBLOCK))
6629 if (exprNode_isDefined (body)
6630 && !exprNode_isBlock (body))
6632 if (context_inIterDef ()
6633 && (body->kind == XPR_STMTLIST
6634 || body->kind == XPR_TOK))
6640 voptgenerror (FLG_FORBLOCK,
6642 ("Body of for statement is not a block: %s",
6643 exprNode_unparse (body)),
6644 exprNode_loc (body));
6650 ** for ud purposes: (alreadly) init -> test -> (now) LOOP: body + inc + test
6653 if (exprNode_isError (body))
6655 ret = exprNode_createPartialCopy (inc);
6659 ret = exprNode_createPartialCopy (body);
6661 ret->exitCode = exitkind_makeConditional (body->exitCode);
6663 exprNode_mergeUSs (inc, body);
6665 if (exprNode_isDefined (inc))
6669 context_setMessageAnnote (cstring_makeLiteral ("in post loop increment"));
6672 tmp = exprNode_effect (exprData_getTripleInc (inc->edata));
6673 exprNode_freeShallow (tmp);
6675 context_clearMessageAnnote ();
6676 context_setMessageAnnote (cstring_makeLiteral ("in post loop test"));
6678 tmp = exprNode_effect (exprData_getTripleTest (inc->edata));
6679 exprNode_freeShallow (tmp);
6681 context_clearMessageAnnote ();
6683 ret->uses = sRefSet_copy (ret->uses, inc->uses);
6684 ret->sets = sRefSet_copy (ret->sets, inc->sets);
6685 ret->msets = sRefSet_copy (ret->msets, inc->msets);
6689 ret->kind = XPR_FOR;
6690 ret->edata = exprData_makePair (inc, body);
6692 if (exprNode_isDefined (inc)) {
6693 exprNode test = exprData_getTripleTest (inc->edata);
6695 if (exprNode_isUndefined (test)) {
6696 if (exprNode_isDefined (body)) {
6697 if (!body->canBreak) {
6698 /* Really, it means never reached. */
6699 ret->exitCode = XK_MUSTEXIT;
6709 ** for (init; test; inc)
6712 ** while (test) { body; inc; }
6714 ** Now: check use of init (may set vars for test)
6715 ** check use of test
6719 /*@observer@*/ guardSet exprNode_getForGuards (exprNode pred)
6723 if (exprNode_isError (pred)) return guardSet_undefined;
6725 llassert (pred->kind == XPR_FORPRED);
6727 test = exprData_getTripleTest (pred->edata);
6729 if (!exprNode_isError (test))
6731 return (test->guards);
6734 return guardSet_undefined;
6737 exprNode exprNode_whilePred (/*@only@*/ exprNode test)
6739 exprNode ret = exprNode_createSemiCopy (test);
6741 if (exprNode_isDefined (test))
6743 exprNode_copySets (ret, test);
6744 exprNode_checkPred (cstring_makeLiteralTemp ("while"), test);
6745 exprNode_checkUse (ret, test->sref, test->loc);
6747 exprNode_produceGuards (test);
6749 ret->guards = guardSet_copy (test->guards);
6752 ret->edata = exprData_makeSingle (test);
6753 ret->kind = XPR_WHILEPRED;
6757 exprNode exprNode_forPred (/*@only@*/ exprNode init, /*@only@*/ exprNode test,
6758 /*@only@*/ exprNode inc)
6763 ** for ud purposes: init -> test -> LOOP: [ body, inc ]
6766 exprNode_checkPred (cstring_makeLiteralTemp ("for"), test);
6768 if (!exprNode_isError (inc))
6770 ret = exprNode_createPartialCopy (inc);
6774 if (!exprNode_isError (init))
6776 ret = exprNode_createPartialCopy (init);
6778 else if (!exprNode_isError (test))
6780 ret = exprNode_createPartialCopy (test);
6784 ret = exprNode_createUnknown ();
6788 exprNode_mergeUSs (ret, init);
6790 if (exprNode_isDefined (init))
6792 exprNode_checkUse (ret, init->sref, init->loc);
6795 exprNode_mergeUSs (ret, test);
6797 if (exprNode_isDefined (test))
6799 exprNode_checkUse (ret, test->sref, test->loc);
6802 ret->kind = XPR_FORPRED;
6803 ret->edata = exprData_makeFor (init, test, inc);
6807 /*@notnull@*/ /*@only@*/ exprNode exprNode_goto (/*@only@*/ cstring label)
6809 exprNode ret = exprNode_createUnknown ();
6811 if (context_inMacro ())
6813 voptgenerror (FLG_MACROSTMT,
6814 message ("Macro %s uses goto (not functional)",
6815 context_inFunctionName ()),
6819 ret->kind = XPR_GOTO;
6820 ret->edata = exprData_makeLiteral (label);
6821 ret->mustBreak = TRUE;
6822 ret->exitCode = XK_GOTO;
6823 ret->canBreak = TRUE;
6827 exprNode exprNode_continue (/*@only@*/ lltok l, int qcontinue)
6829 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
6831 ret->kind = XPR_CONTINUE;
6832 ret->edata = exprData_makeTok (l);
6833 ret->canBreak = TRUE;
6834 ret->mustBreak = TRUE;
6836 if (qcontinue == QSAFEBREAK)
6840 else if (qcontinue == QINNERCONTINUE)
6842 if (!context_inDeepLoop ())
6845 (FLG_LOOPLOOPCONTINUE,
6846 cstring_makeLiteral ("Continue statement marked with innercontinue "
6847 "is not inside a nested loop"),
6848 exprNode_loc (ret));
6851 else if (qcontinue == BADTOK)
6853 if (context_inDeepLoop ())
6856 (FLG_LOOPLOOPCONTINUE,
6857 cstring_makeLiteral ("Continue statement in nested loop"),
6858 exprNode_loc (ret));
6863 llbuglit ("exprNode_continue: bad qcontinue");
6869 exprNode exprNode_break (/*@only@*/ lltok l, int bqual)
6871 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
6872 clause breakClause = context_breakClause ();
6874 ret->kind = XPR_BREAK;
6875 ret->edata = exprData_makeTok (l);
6876 ret->canBreak = TRUE;
6877 ret->mustBreak = TRUE;
6879 if (breakClause == NOCLAUSE)
6883 cstring_makeLiteral ("Break not inside while, for or switch statement"),
6884 exprNode_loc (ret));
6888 if (bqual != BADTOK)
6895 if (breakClause == SWITCHCLAUSE)
6897 if (!context_inDeepSwitch ())
6899 voptgenerror (FLG_SYNTAX,
6901 ("Break preceded by innerbreak is not in a deep switch"),
6902 exprNode_loc (ret));
6907 if (!context_inDeepLoop ())
6909 voptgenerror (FLG_SYNTAX,
6911 ("Break preceded by innerbreak is not in a deep loop"),
6912 exprNode_loc (ret));
6917 if (breakClause == SWITCHCLAUSE)
6919 voptgenerror (FLG_SYNTAX,
6921 ("Break preceded by loopbreak is breaking a switch"),
6922 exprNode_loc (ret));
6926 if (breakClause != SWITCHCLAUSE)
6930 message ("Break preceded by switchbreak is breaking %s",
6931 cstring_makeLiteralTemp
6932 ((breakClause == WHILECLAUSE
6933 || breakClause == DOWHILECLAUSE) ? "a while loop"
6934 : (breakClause == FORCLAUSE) ? "a for loop"
6935 : (breakClause == ITERCLAUSE) ? "an iterator"
6937 exprNode_loc (ret));
6945 if (breakClause == SWITCHCLAUSE)
6947 clause nextBreakClause = context_nextBreakClause ();
6949 switch (nextBreakClause)
6951 case NOCLAUSE: break;
6957 (FLG_LOOPSWITCHBREAK,
6958 cstring_makeLiteral ("Break statement in switch inside loop"),
6959 exprNode_loc (ret));
6963 (FLG_SWITCHSWITCHBREAK,
6964 cstring_makeLiteral ("Break statement in switch inside switch"),
6965 exprNode_loc (ret));
6972 if (context_inDeepLoop ())
6976 cstring_makeLiteral ("Break statement in nested loop"),
6977 exprNode_loc (ret));
6981 if (context_inDeepLoopSwitch ())
6984 (FLG_SWITCHLOOPBREAK,
6985 cstring_makeLiteral ("Break statement in loop inside switch"),
6986 exprNode_loc (ret));
6996 exprNode exprNode_nullReturn (/*@only@*/ lltok t)
6998 fileloc loc = lltok_getLoc (t);
6999 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
7001 context_returnFunction ();
7002 exprChecks_checkNullReturn (loc);
7004 ret->kind = XPR_NULLRETURN;
7005 ret->edata = exprData_makeTok (t);
7006 ret->exitCode = XK_MUSTRETURN;
7010 exprNode exprNode_return (/*@only@*/ exprNode e)
7014 if (exprNode_isError (e))
7016 ret = exprNode_createUnknown ();
7020 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (e->loc));
7022 exprNode_checkUse (ret, e->sref, e->loc);
7023 exprNode_checkReturn (e);
7026 context_returnFunction ();
7027 ret->kind = XPR_RETURN;
7028 ret->edata = exprData_makeSingle (e);
7029 ret->exitCode = XK_MUSTRETURN;
7034 exprNode exprNode_comma (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
7038 if (exprNode_isError (e1))
7040 if (exprNode_isError (e2))
7042 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
7046 ret = exprNode_createPartialCopy (e2);
7047 exprNode_checkUse (ret, e2->sref, e2->loc);
7048 ret->sref = e2->sref;
7053 ret = exprNode_createPartialCopy (e1);
7055 exprNode_checkUse (ret, e1->sref, e1->loc);
7057 if (!exprNode_isError (e2))
7059 exprNode_mergeUSs (ret, e2);
7060 exprNode_checkUse (ret, e2->sref, e2->loc);
7061 ret->sref = e2->sref;
7065 ret->kind = XPR_COMMA;
7066 ret->edata = exprData_makePair (e1, e2);
7068 if (exprNode_isDefined (e1))
7070 if (exprNode_isDefined (e2))
7074 if (exprNode_mustEscape (e1) || e1->mustBreak)
7078 message ("Second clause of comma expression is unreachable: %s",
7079 exprNode_unparse (e2)),
7083 ret->exitCode = exitkind_combine (e1->exitCode, e2->exitCode);
7084 ret->mustBreak = e1->mustBreak || e2->mustBreak;
7085 ret->canBreak = e1->canBreak || e2->canBreak;
7089 if (exprNode_mustEscape (e1) || e1->mustBreak)
7093 message ("Second clause of comma expression is unreachable: %s",
7094 exprNode_unparse (e2)),
7098 ret->exitCode = e1->exitCode;
7099 ret->canBreak = e1->canBreak;
7104 if (exprNode_isDefined (e2))
7106 ret->exitCode = e2->exitCode;
7107 ret->mustBreak = e2->mustBreak;
7108 ret->canBreak = e2->canBreak;
7115 static bool exprNode_checkOneInit (/*@notnull@*/ exprNode el, exprNode val)
7117 ctype t1 = exprNode_getType (el);
7118 ctype t2 = exprNode_getType (val);
7119 bool hasError = FALSE;
7121 if (ctype_isUnknown (t1))
7123 voptgenerror (FLG_IMPTYPE,
7124 message ("Variable has unknown (implicitly int) type: %s",
7125 exprNode_unparse (el)),
7129 el->typ = ctype_int;
7132 if (exprNode_isDefined (val) && val->kind == XPR_INITBLOCK)
7134 exprNodeList vals = exprData_getArgs (val->edata);
7136 if (ctype_isRealAP (t1))
7141 exprNodeList_elements (vals, oneval)
7143 cstring istring = message ("%d", i);
7146 (exprNode_fakeCopy (el),
7147 exprNode_numLiteral (ctype_int, istring,
7148 fileloc_copy (el->loc), i));
7150 if (exprNode_isDefined (newel))
7152 if (exprNodeList_size (vals) == 1
7153 && ctype_isString (exprNode_getType (oneval))
7154 && ctype_isChar (exprNode_getType (newel)))
7156 exprNode_freeIniter (newel);
7160 if (exprNode_checkOneInit (newel, oneval))
7165 if (nerrors > 3 && exprNodeList_size (vals) > 6)
7168 (message ("Additional initialization errors "
7169 "for %s not reported",
7170 exprNode_unparse (el)),
7172 exprNode_freeIniter (newel);
7177 exprNode_freeIniter (newel);
7182 exprNode_freeIniter (newel);
7187 cstring_free (istring);
7190 } end_exprNodeList_elements;
7193 else if (ctype_isStruct (ctype_realType (t1)))
7195 uentryList fields = ctype_getFields (t1);
7198 if (uentryList_size (fields) != exprNodeList_size (vals))
7200 if (uentryList_size (fields) > exprNodeList_size (vals))
7202 hasError = optgenerror
7204 message ("Initializer block for "
7205 "%s has %d field%p, but %s has %d field%p: %q",
7206 exprNode_unparse (el),
7207 exprNodeList_size (vals),
7209 uentryList_size (fields),
7210 exprNodeList_unparse (vals)),
7215 hasError = optgenerror
7217 message ("Initializer block for "
7218 "%s has %d field%p, but %s has %d field%p: %q",
7219 exprNode_unparse (el),
7220 exprNodeList_size (vals),
7222 uentryList_size (fields),
7223 exprNodeList_unparse (vals)),
7229 exprNodeList_elements (vals, oneval)
7231 uentry thisfield = uentryList_getN (fields, i);
7233 exprNode_fieldAccess (exprNode_fakeCopy (el),
7234 uentry_getName (thisfield));
7236 if (exprNode_isDefined (newel))
7238 if (exprNode_checkOneInit (newel, oneval))
7243 exprNode_freeIniter (newel);
7247 } end_exprNodeList_elements;
7252 hasError = optgenerror
7254 message ("Initializer block used for "
7255 "%s where %t is expected: %s",
7256 exprNode_unparse (el), t1, exprNode_unparse (val)),
7262 if (exprNode_isDefined (val))
7264 doAssign (el, val, TRUE);
7266 if (!exprNode_matchType (t1, val))
7268 hasError = gentypeerror
7270 message ("Initial value of %s is type %t, "
7272 exprNode_unparse (el),
7273 t2, t1, exprNode_unparse (val)),
7282 exprNode exprNode_makeInitialization (/*@only@*/ idDecl t,
7283 /*@only@*/ exprNode e)
7285 uentry ue = usymtab_lookup (idDecl_observeId (t));
7286 bool isUsed = uentry_isUsed (ue);
7287 exprNode ret = exprNode_fromIdentifierAux (ue);
7288 ctype ct = ctype_realishType (ret->typ);
7291 if (ctype_isUnknown (ct))
7293 voptgenerror (FLG_IMPTYPE,
7294 message ("Variable has unknown (implicitly int) type: %s",
7295 idDecl_getName (t)),
7296 exprNode_isDefined (e) ? exprNode_loc (e) : g_currentloc);
7301 if (exprNode_isError (e))
7303 e = exprNode_createUnknown ();
7306 /* error: assume initializer is defined */
7307 sRef_setDefined (ret->sref, loc);
7311 loc = exprNode_loc (e);
7316 ** was addSafeUse --- what's the problem?
7318 ** int x = 3, y = x ?
7321 exprNode_checkUse (ret, e->sref, e->loc);
7323 if (ctype_isUnknown (e->typ) && uentry_isValid (ue))
7325 exprNode lhs = exprNode_createId (ue);
7328 ** static storage should be undefined before initializing
7331 if (uentry_isStatic (ue))
7333 sRef_setDefState (lhs->sref, SS_PARTIAL, fileloc_undefined);
7336 (void) exprNode_checkOneInit (lhs, e);
7338 if (uentry_isStatic (ue))
7340 sRef_setDefState (lhs->sref, SS_DEFINED, fileloc_undefined);
7343 exprNode_free (lhs);
7347 if (!exprNode_matchType (ct, e))
7349 if (exprNode_isZero (e) && ctype_isArrayPtr (ct))
7356 (exprNode_getType (e), e, exprNode_getType (ret), ret,
7358 ("Variable %s initialized to type %t, expects %t: %s",
7359 exprNode_unparse (ret), exprNode_getType (e),
7360 exprNode_getType (ret),
7361 exprNode_unparse (e)),
7367 if (uentry_isStatic (ue))
7369 sRef_setDefState (ret->sref, SS_PARTIAL, fileloc_undefined);
7372 doAssign (ret, e, TRUE);
7374 if (uentry_isStatic (ue))
7376 sRef_setDefState (ret->sref, SS_DEFINED, fileloc_undefined);
7380 if (context_inIterDef ())
7382 /* should check if it is yield */
7383 uentry_setUsed (ue, loc);
7387 if (!isUsed) /* could be @unused@-qualified variable */
7389 uentry_setNotUsed (ue);
7393 ret->exitCode = XK_NEVERESCAPE;
7394 ret->mustBreak = FALSE;
7397 ** Must be before new kind is assigned!
7400 exprData_free (ret->edata, ret->kind);
7402 ret->kind = XPR_INIT;
7403 ret->edata = exprData_makeInit (t, e);
7404 exprNode_mergeUSs (ret, e);
7408 exprNode exprNode_iter (/*@observer@*/ uentry name,
7409 /*@only@*/ exprNodeList alist,
7410 /*@only@*/ exprNode body,
7411 /*@observer@*/ uentry end)
7416 llassert (uentry_isValid (name));
7418 uentry_setUsed (name, exprNode_loc (body));
7420 ret = exprNode_createPartialCopy (body);
7421 iname = uentry_getName (name);
7423 if (uentry_isInvalid (end))
7426 message ("Iter %s not balanced with end_%s", iname, iname));
7430 cstring ename = uentry_getName (end);
7432 if (!cstring_equalPrefix (ename, "end_"))
7434 llerror (FLG_ITER, message ("Iter %s not balanced with end_%s: %s",
7435 iname, iname, ename));
7439 if (!cstring_equal (iname, cstring_suffix (ename, 4)))
7442 message ("Iter %s not balanced with end_%s: %s",
7443 iname, iname, ename));
7447 cstring_free (ename);
7450 context_exitIterClause (body);
7452 ret->kind = XPR_ITER;
7453 ret->edata = exprData_makeIter (name, alist, body, end);
7455 if (uentry_isIter (name))
7457 (void) checkArgsReal (name, body,
7458 uentry_getParams (name), alist, TRUE, ret);
7461 cstring_free (iname);
7467 exprNode_iterNewId (/*@only@*/ cstring s)
7469 exprNode e = exprNode_new ();
7470 uentry ue = uentryList_getN (uentry_getParams (getCurrentIter ()), iterParamNo ());
7472 llassert (processingIterVars ());
7474 e->loc = context_getSaveLocation ();
7476 if (fileloc_isUndefined (e->loc))
7478 fileloc_free (e->loc);
7479 e->loc = fileloc_copy (g_currentloc);
7482 e->uses = sRefSet_new ();
7483 e->sets = sRefSet_new ();
7484 e->msets = sRefSet_new ();
7486 e->val = multiVal_unknown ();
7487 e->guards = guardSet_new ();
7489 e->isJumpPoint = FALSE;
7490 e->exitCode = XK_NEVERESCAPE;
7492 /*> missing fields, detected by lclint <*/
7493 e->canBreak = FALSE;
7494 e->mustBreak = FALSE;
7495 e->etext = cstring_undefined;
7497 if (uentry_isYield (ue))
7499 uentry uue = uentry_makeVariable (s, uentry_getType (ue),
7500 fileloc_copy (e->loc),
7504 uue = usymtab_supEntrySrefReturn (uue);
7506 sr = uentry_getSref (uue);
7507 sRef_mergeStateQuiet (sr, uentry_getSref (ue));
7508 sr = uentry_getSref (uue);
7509 sRef_setDefined (sr, e->loc);
7511 e->typ = uentry_getType (uue);
7513 e->edata = exprData_makeId (uue);
7514 uentry_setUsed (uue, g_currentloc);
7520 sRef_setGlobalScope ();
7521 uue = uentry_makeVariableLoc (s, ctype_unknown);
7523 e->typ = ctype_unknown;
7524 e->edata = exprData_makeId (uue);
7526 uentry_setUsed (uue, e->loc);
7527 uentry_setHasNameError (uue);
7529 if (context_getFlag (FLG_REPEATUNRECOG))
7531 uentry_markOwned (uue);
7535 usymtab_supGlobalEntry (uue);
7538 sRef_clearGlobalScope ();
7540 voptgenerror (FLG_UNRECOG, message ("Unrecognized identifier: %s", s),
7547 exprNode_defineConstraints(e);
7552 exprNode_iterExpr (/*@returned@*/ exprNode e)
7554 if (!processingIterVars ())
7556 llcontbuglit ("checkIterParam: not in iter");
7560 if (uentry_isYield (uentryList_getN (uentry_getParams (getCurrentIter ()),
7563 if (exprNode_isDefined (e))
7565 if (fileloc_isDefined (e->loc))
7569 message ("Yield parameter is not simple identifier: %s",
7570 exprNode_unparse (e)),
7577 message ("Yield parameter is not simple identifier: %s",
7578 exprNode_unparse (e)),
7588 exprNode_iterId (/*@observer@*/ uentry c)
7592 llassert (processingIterVars ());
7594 ue = uentryList_getN (uentry_getParams (getCurrentIter ()),
7597 if (uentry_isYield (ue))
7599 ctype ct = uentry_getType (ue);
7600 exprNode e = exprNode_createPlain (ct);
7601 cstring name = uentry_getName (c);
7602 uentry le = uentry_makeVariable (name, ct, fileloc_undefined, FALSE);
7604 uentry_setUsed (ue, g_currentloc);
7605 uentry_setHasNameError (ue);
7607 cstring_free (name);
7610 e->edata = exprData_makeId (le);
7611 e->loc = context_getSaveLocation ();
7612 e->sref = uentry_getSref (le);
7614 usymtab_supEntrySref (le);
7616 if (!context_inHeader ())
7620 message ("Yield parameter shadows local declaration: %q",
7621 uentry_getName (c)),
7622 fileloc_isDefined (e->loc) ? e->loc : g_currentloc))
7624 uentry_showWhereDeclared (c);
7631 return (exprNode_fromIdentifierAux (c));
7634 exprNode exprNode_iterStart (/*@observer@*/ uentry name, /*@only@*/ exprNodeList alist)
7636 exprNode ret = exprNode_create (ctype_unknown);
7638 ret->kind = XPR_ITERCALL;
7639 ret->edata = exprData_makeIterCall (name, alist);
7641 if (uentry_isIter (name))
7643 uentryList params = uentry_getParams (name);
7645 if (context_inIterDef ()
7646 && uentryList_size (params) == exprNodeList_size (alist))
7650 exprNodeList_elements (alist, arg)
7652 uentry parg = uentryList_getN (params, i);
7654 if (uentry_isYield (parg))
7656 uentry ue = exprNode_getUentry (arg);
7658 if (uentry_isValid (ue))
7665 } end_exprNodeList_elements;
7668 (void) checkArgsReal (name, ret, params, alist, TRUE, ret);
7669 checkUnspecCall (ret, params, alist);
7675 /*@exposed@*/ sRef exprNode_getSref (exprNode e)
7677 if (exprNode_isDefined (e))
7680 if (e->sref == defref) /*@noaccess sRef@*/
7683 e->sref = sRef_makeUnknown ();
7684 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
7695 return sRef_undefined;
7699 /*@observer@*/ cstring
7700 exprNode_unparseFirst (exprNode e)
7702 if (exprNode_isDefined (e))
7706 if (e->kind == XPR_STMTLIST
7707 || e->kind == XPR_COMMA || e->kind == XPR_COND)
7709 exprNode first = exprData_getPairA (e->edata);
7711 if (exprNode_isDefined (first))
7713 return (exprNode_unparseFirst (exprData_getPairA (e->edata)));
7717 return (cstring_makeLiteralTemp ("..."));
7721 ret = cstring_elide (exprNode_unparse (e), 20);
7722 cstring_markOwned (ret);
7728 return cstring_makeLiteralTemp ("<error>");
7732 /*@observer@*/ cstring
7733 exprNode_unparse (exprNode e)
7735 if (exprNode_isError (e))
7737 return cstring_makeLiteralTemp ("<error>");
7740 if (cstring_isDefined (e->etext))
7746 cstring ret = exprNode_doUnparse (e);
7748 /*@-modifies@*/ /* benevolent */
7755 /*@observer@*/ fileloc
7756 exprNode_loc (exprNode e)
7758 if (exprNode_isError (e))
7760 return (g_currentloc);
7769 ** executes exprNode e
7770 ** recursively rexecutes as though in original parse using
7771 ** information in e->edata
7774 static /*@only@*/ exprNodeList exprNodeList_effect (exprNodeList e)
7776 exprNodeList ret = exprNodeList_new ();
7778 exprNodeList_elements (e, current)
7780 exprNodeList_addh (ret, exprNode_effect (current));
7781 } end_exprNodeList_elements;
7786 static /*@only@*/ exprNode exprNode_effect (exprNode e)
7787 /*@globals internalState@*/
7789 bool innerEffect = inEffect;
7795 context_clearJustPopped ();
7797 if (exprNode_isError (e))
7799 ret = exprNode_undefined;
7804 ** Turn off expose and dependent transfer checking.
7805 ** Need to pass exposed internal nodes,
7806 ** [ copying would be a waste! ]
7807 ** [ Actually, I think I wasted a lot more time than its worth ]
7808 ** [ trying to do this. ]
7812 /*@-observertrans@*/
7813 /*@-dependenttrans@*/
7820 ret = exprNode_addParens (exprData_getUopTok (data),
7821 exprNode_effect (exprData_getUopNode (data)));
7824 ret = exprNode_assign (exprNode_effect (exprData_getOpA (data)),
7825 exprNode_effect (exprData_getOpB (data)),
7826 exprData_getOpTok (data));
7829 ret = exprNode_undefined;
7832 ret = exprNode_functionCall (exprNode_effect (exprData_getFcn (data)),
7833 exprNodeList_effect (exprData_getArgs (data)));
7846 cstring id = exprData_getId (data);
7847 uentry ue = usymtab_lookupSafe (id);
7849 ret = exprNode_fromIdentifierAux (ue);
7850 ret->loc = fileloc_update (ret->loc, e->loc);
7857 ret = exprNode_arrayFetch (exprNode_effect (exprData_getPairA (data)),
7858 exprNode_effect (exprData_getPairB (data)));
7861 ret = exprNode_op (exprNode_effect (exprData_getOpA (data)),
7862 exprNode_effect (exprData_getOpB (data)),
7863 exprData_getOpTok (data));
7867 ret = exprNode_postOp (exprNode_effect (exprData_getUopNode (data)),
7868 exprData_getUopTok (data));
7871 ret = exprNode_preOp (exprNode_effect (exprData_getUopNode (data)),
7872 exprData_getUopTok (data));
7884 ret = exprNode_vaArg (exprData_getCastTok (data),
7885 exprNode_effect (exprData_getCastNode (data)),
7886 exprData_getCastType (data));
7890 ret = exprNode_cast (exprData_getCastTok (data),
7891 exprNode_effect (exprData_getCastNode (data)),
7892 exprData_getCastType (data));
7895 ret = exprNode_iterStart (exprData_getIterCallIter (data),
7897 (exprData_getIterCallArgs (data)));
7901 ret = exprNode_iter (exprData_getIterSname (data),
7902 exprNodeList_effect (exprData_getIterAlist (data)),
7903 exprNode_effect (exprData_getIterBody (data)),
7904 exprData_getIterEname (data));
7908 ret = exprNode_for (exprNode_effect (exprData_getPairA (data)),
7909 exprNode_effect (exprData_getPairB (data)));
7913 ret = exprNode_forPred (exprNode_effect (exprData_getTripleInit (data)),
7914 exprNode_effect (exprData_getTripleTest (data)),
7915 exprNode_effect (exprData_getTripleInc (data)));
7919 ret = exprNode_createTok (exprData_getTok (data));
7923 ret = exprNode_goto (exprData_getLiteral (data));
7924 ret->loc = fileloc_update (ret->loc, e->loc);
7928 ret = exprNode_continue (exprData_getTok (data), QSAFEBREAK);
7932 ret = exprNode_break (exprData_getTok (data), QSAFEBREAK);
7936 ret = exprNode_return (exprNode_effect (exprData_getSingle (data)));
7939 case XPR_NULLRETURN:
7940 ret = exprNode_nullReturn (exprData_getTok (data));
7944 ret = exprNode_comma (exprNode_effect (exprData_getPairA (data)),
7945 exprNode_effect (exprData_getPairB (data)));
7949 ret = exprNode_cond (exprNode_effect (exprData_getTriplePred (data)),
7950 exprNode_effect (exprData_getTripleTrue (data)),
7951 exprNode_effect (exprData_getTripleFalse (data)));
7954 ret = exprNode_if (exprNode_effect (exprData_getPairA (data)),
7955 exprNode_effect (exprData_getPairB (data)));
7959 ret = exprNode_ifelse (exprNode_effect (exprData_getTriplePred (data)),
7960 exprNode_effect (exprData_getTripleTrue (data)),
7961 exprNode_effect (exprData_getTripleFalse (data)));
7964 ret = exprNode_whilePred (exprData_getSingle (data));
7968 ret = exprNode_while (exprNode_effect (exprData_getPairA (data)),
7969 exprNode_effect (exprData_getPairB (data)));
7973 ret = exprNode_doWhile (exprNode_effect (exprData_getPairA (data)),
7974 exprNode_effect (exprData_getPairB (data)));
7978 ret = exprNode_makeBlock (exprNode_effect (exprData_getSingle (data)));
7982 ret = exprNode_statement (exprNode_effect (exprData_getUopNode (data)),
7983 exprData_getUopTok (data));
7987 ret = exprNode_concat (exprNode_effect (exprData_getPairA (data)),
7988 exprNode_effect (exprData_getPairB (data)));
7993 ret = exprNode_caseMarker
7994 (exprNode_effect (exprData_getSingle (data)),
8000 ret = exprNode_createTok (exprData_getTok (data));
8004 ret = exprNode_switch (exprNode_effect (exprData_getPairA (data)),
8005 exprNode_effect (exprData_getPairB (data)));
8009 ret = exprNode_makeInitialization
8010 (exprData_getInitId (data),
8011 exprNode_effect (exprData_getInitNode (data)));
8015 ret = exprNode_fieldAccess (exprNode_effect (exprData_getFieldNode (data)),
8016 cstring_copy (exprData_getFieldName (data)));
8020 ret = exprNode_arrowAccess (exprNode_effect (exprData_getFieldNode (data)),
8021 cstring_copy (exprData_getFieldName (data)));
8024 case XPR_STRINGLITERAL:
8038 /*@=observertrans@*/
8040 /*@=dependenttrans@*/
8051 static /*@observer@*/ cstring exprNode_rootVarName (exprNode e)
8056 if (exprNode_isError (e))
8058 return cstring_undefined;
8066 ret = exprNode_rootVarName (exprData_getUopNode (data));
8069 ret = exprNode_rootVarName (exprData_getOpA (data));
8073 ret = exprData_getId (data);
8098 case XPR_NULLRETURN:
8121 case XPR_STRINGLITERAL:
8122 ret = cstring_undefined;
8130 static /*@only@*/ cstring exprNode_doUnparse (exprNode e)
8135 if (exprNode_isError (e))
8137 static /*@only@*/ cstring error = cstring_undefined;
8139 if (!cstring_isDefined (error))
8141 error = cstring_makeLiteral ("<error>");
8152 ret = message ("(%s)", exprNode_unparse (exprData_getUopNode (e->edata)));
8155 ret = message ("%s %s %s",
8156 exprNode_unparse (exprData_getOpA (data)),
8157 lltok_unparse (exprData_getOpTok (data)),
8158 exprNode_unparse (exprData_getOpB (data)));
8161 ret = message ("%s(%q)",
8162 exprNode_unparse (exprData_getFcn (data)),
8163 exprNodeList_unparse (exprData_getArgs (data)));
8166 ret = message ("{ %q }", exprNodeList_unparse (exprData_getArgs (data)));
8169 ret = cstring_undefined;
8172 ret = message ("%s:", exprData_getId (data));
8176 ret = cstring_copy (exprData_getId (data));
8179 ret = message ("%s[%s]", exprNode_unparse (exprData_getPairA (data)),
8180 exprNode_unparse (exprData_getPairB (data)));
8183 ret = message ("<body>");
8186 ret = message ("%s %s %s",
8187 exprNode_unparse (exprData_getOpA (data)),
8188 lltok_unparse (exprData_getOpTok (data)),
8189 exprNode_unparse (exprData_getOpB (data)));
8193 ret = message ("%s%s",
8194 lltok_unparse (exprData_getUopTok (data)),
8195 exprNode_unparse (exprData_getUopNode (data)));
8199 ret = message ("%s%s",
8200 exprNode_unparse (exprData_getUopNode (data)),
8201 lltok_unparse (exprData_getUopTok (data)));
8205 ret = message ("offsetof(%s,%q)",
8206 ctype_unparse (qtype_getType (exprData_getOffsetType (data))),
8207 cstringList_unparseSep (exprData_getOffsetName (data), cstring_makeLiteralTemp (".")));
8211 ret = message ("sizeof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
8215 ret = message ("sizeof(%s)", exprNode_unparse (exprData_getSingle (data)));
8219 ret = message ("alignof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
8223 ret = message ("alignof(%s)", exprNode_unparse (exprData_getSingle (data)));
8227 ret = message ("va_arg(%s, %q)",
8228 exprNode_unparse (exprData_getCastNode (data)),
8229 qtype_unparse (exprData_getCastType (data)));
8233 ret = message ("%q(%q)",
8234 uentry_getName (exprData_getIterCallIter (data)),
8235 exprNodeList_unparse (exprData_getIterCallArgs (data)));
8238 ret = message ("%q(%q) %s %q",
8239 uentry_getName (exprData_getIterSname (data)),
8240 exprNodeList_unparse (exprData_getIterAlist (data)),
8241 exprNode_unparse (exprData_getIterBody (data)),
8242 uentry_getName (exprData_getIterEname (data)));
8245 ret = message ("(%q)%s",
8246 qtype_unparse (exprData_getCastType (data)),
8247 exprNode_unparse (exprData_getCastNode (data)));
8251 ret = message ("%s %s",
8252 exprNode_unparse (exprData_getPairA (data)),
8253 exprNode_unparse (exprData_getPairB (data)));
8257 ret = message ("for (%s; %s; %s)",
8258 exprNode_unparse (exprData_getTripleInit (data)),
8259 exprNode_unparse (exprData_getTripleTest (data)),
8260 exprNode_unparse (exprData_getTripleInc (data)));
8264 ret = message ("goto %s", exprData_getLiteral (data));
8268 ret = cstring_makeLiteral ("continue");
8272 ret = cstring_makeLiteral ("break");
8276 ret = message ("return %s", exprNode_unparse (exprData_getSingle (data)));
8279 case XPR_NULLRETURN:
8280 ret = cstring_makeLiteral ("return");
8284 ret = message ("%s, %s",
8285 exprNode_unparse (exprData_getPairA (data)),
8286 exprNode_unparse (exprData_getPairB (data)));
8290 ret = message ("%s ? %s : %s",
8291 exprNode_unparse (exprData_getTriplePred (data)),
8292 exprNode_unparse (exprData_getTripleTrue (data)),
8293 exprNode_unparse (exprData_getTripleFalse (data)));
8296 ret = message ("if (%s) %s",
8297 exprNode_unparse (exprData_getPairA (data)),
8298 exprNode_unparse (exprData_getPairB (data)));
8302 ret = message ("if (%s) %s else %s",
8303 exprNode_unparse (exprData_getTriplePred (data)),
8304 exprNode_unparse (exprData_getTripleTrue (data)),
8305 exprNode_unparse (exprData_getTripleFalse (data)));
8308 ret = message ("while (%s) %s",
8309 exprNode_unparse (exprData_getPairA (data)),
8310 exprNode_unparse (exprData_getPairB (data)));
8314 ret = cstring_copy (exprNode_unparse (exprData_getSingle (data)));
8318 ret = cstring_copy (lltok_unparse (exprData_getTok (data)));
8322 ret = message ("do { %s } while (%s)",
8323 exprNode_unparse (exprData_getPairB (data)),
8324 exprNode_unparse (exprData_getPairA (data)));
8328 ret = message ("{ %s }", exprNode_unparseFirst (exprData_getSingle (data)));
8332 ret = cstring_copy (exprNode_unparse (exprData_getUopNode (data)));
8336 ret = message ("%s; %s",
8337 exprNode_unparse (exprData_getPairA (data)),
8338 exprNode_unparse (exprData_getPairB (data)));
8343 ret = cstring_makeLiteral ("default:");
8347 ret = message ("switch (%s) %s",
8348 exprNode_unparse (exprData_getPairA (data)),
8349 exprNode_unparse (exprData_getPairB (data)));
8354 ret = message ("case %s:",
8355 exprNode_unparse (exprData_getSingle (data)));
8359 ret = message ("%s = %s",
8360 idDecl_getName (exprData_getInitId (data)),
8361 exprNode_unparse (exprData_getInitNode (data)));
8365 ret = message ("%s.%s",
8366 exprNode_unparse (exprData_getFieldNode (data)),
8367 exprData_getFieldName (data));
8371 ret = message ("%s->%s",
8372 exprNode_unparse (exprData_getFieldNode (data)),
8373 exprData_getFieldName (data));
8376 case XPR_STRINGLITERAL:
8377 ret = cstring_copy (exprData_getLiteral (data));
8381 ret = cstring_copy (exprData_getLiteral (data));
8385 ret = cstring_makeLiteral ("<node>");
8393 exprNode_isCharLit (exprNode e)
8395 if (exprNode_isDefined (e))
8397 return (multiVal_isChar (exprNode_getValue (e)));
8406 exprNode_isNumLit (exprNode e)
8408 if (exprNode_isDefined (e))
8410 return (multiVal_isInt (exprNode_getValue (e)));
8419 exprNode_isFalseConstant (exprNode e)
8421 if (exprNode_isDefined (e))
8423 cstring s = exprNode_rootVarName (e);
8425 if (cstring_equal (s, context_getFalseName ()))
8435 exprNode_matchLiteral (ctype expected, exprNode e)
8437 if (exprNode_isDefined (e))
8439 multiVal m = exprNode_getValue (e);
8441 if (multiVal_isDefined (m))
8443 if (multiVal_isInt (m))
8445 long int val = multiVal_forceInt (m);
8447 if (ctype_isDirectBool (ctype_realishType (expected)))
8451 return FALSE; /* really?! return TRUE; allow use of 0 for FALSE */
8459 if (ctype_isRealInt (expected))
8462 ** unsigned <- [ constant >= 0 is okay ]
8465 if (ctype_isUnsigned (expected))
8474 ** No checks on sizes of integers...maybe add
8478 DPRINTF (("Here: %s => %s", exprNode_unparse (e), ctype_unparse (expected)));
8479 DPRINTF (("Type: %s / %s", ctype_unparse (exprNode_getType (e)),
8480 bool_unparse (ctype_isInt (exprNode_getType (e)))));
8482 if (context_getFlag (FLG_NUMLITERAL)
8483 && (ctype_isRegularInt (exprNode_getType (e)) || val == 0)) {
8489 return FALSE; /* evs 2000-05-17: previously, always returned TRUE */
8493 else if (ctype_isChar (expected))
8497 else if (ctype_isArrayPtr (expected))
8501 else if (ctype_isAnyFloat (expected))
8503 return (context_getFlag (FLG_NUMLITERAL));
8510 else if (multiVal_isDouble (m))
8512 if (ctype_isAnyFloat (expected))
8517 else if (multiVal_isChar (m))
8519 char val = multiVal_forceChar (m);
8521 if (ctype_isChar (expected))
8523 if (ctype_isUnsigned (expected) && ((int)val) < 0)
8544 exprNode_matchType (ctype expected, exprNode e)
8548 if (!exprNode_isDefined (e)) return TRUE;
8550 actual = ctype_realishType (exprNode_getType (e));
8552 if (ctype_match (ctype_realishType (expected), actual))
8557 llassert (!exprNode_isError (e));
8558 return (exprNode_matchLiteral (expected, e));
8562 exprNode_matchTypes (exprNode e1, exprNode e2)
8567 if (!exprNode_isDefined (e1)) return TRUE;
8568 if (!exprNode_isDefined (e2)) return TRUE;
8571 ** realish type --- keep bools, bools
8574 t1 = ctype_realishType (exprNode_getType (e1));
8575 t2 = ctype_realishType (exprNode_getType (e2));
8577 if (ctype_match (t1, t2))
8582 return (exprNode_matchLiteral (t1, e2) || exprNode_matchLiteral (t2, e1));
8590 exprNode_matchArgType (ctype ct, exprNode e)
8594 if (!exprNode_isDefined (e))
8599 et = ctype_realType (exprNode_getType (e));
8601 if (ctype_matchArg (ct, et)) return TRUE;
8603 llassert (!exprNode_isError (e));
8604 return (exprNode_matchLiteral (ct, e));
8607 static /*@only@*/ exprNodeSList
8608 exprNode_flatten (/*@dependent@*/ exprNode e) /*@*/
8610 if (exprNode_isDefined (e))
8612 if (e->kind == XPR_STMTLIST)
8614 return (exprNodeSList_append
8615 (exprNode_flatten (exprData_getPairA (e->edata)),
8616 exprNode_flatten (exprData_getPairB (e->edata))));
8618 else if (e->kind == XPR_BLOCK)
8620 return (exprNode_flatten (exprData_getSingle (e->edata)));
8624 return (exprNodeSList_singleton (e));
8628 return exprNodeSList_new ();
8631 static /*@exposed@*/ exprNode
8632 exprNode_lastStatement (/*@returned@*/ exprNode e)
8634 if (exprNode_isDefined (e))
8636 if (e->kind == XPR_STMTLIST)
8638 exprNode b = exprData_getPairB (e->edata);
8640 if (exprNode_isDefined (b))
8642 return exprNode_lastStatement (b);
8646 return exprNode_lastStatement (exprData_getPairA (e->edata));
8649 else if (e->kind == XPR_BLOCK)
8651 return (exprNode_lastStatement (exprData_getSingle (e->edata)));
8659 return exprNode_undefined;
8662 static /*@exposed@*/ exprNode
8663 exprNode_firstStatement (/*@returned@*/ exprNode e)
8665 if (exprNode_isDefined (e))
8667 if (e->kind == XPR_STMTLIST)
8669 exprNode b = exprData_getPairA (e->edata);
8671 if (exprNode_isDefined (b))
8673 return exprNode_firstStatement (b);
8677 return exprNode_firstStatement (exprData_getPairB (e->edata));
8680 else if (e->kind == XPR_BLOCK)
8682 return (exprNode_firstStatement (exprData_getSingle (e->edata)));
8690 return exprNode_undefined;
8694 exprNode_mergeUSs (exprNode res, exprNode other)
8696 if (exprNode_isDefined (res) && exprNode_isDefined (other))
8698 res->msets = sRefSet_union (res->msets, other->msets);
8699 res->sets = sRefSet_union (res->sets, other->sets);
8700 res->uses = sRefSet_union (res->uses, other->uses);
8705 exprNode_mergeCondUSs (exprNode res, exprNode other1, exprNode other2)
8707 if (exprNode_isDefined (res))
8709 if (exprNode_isDefined (other1))
8711 res->sets = sRefSet_union (res->sets, other1->sets);
8712 res->msets = sRefSet_union (res->msets, other1->msets);
8713 res->uses = sRefSet_union (res->uses, other1->uses);
8715 if (exprNode_isDefined (other2))
8717 res->sets = sRefSet_union (res->sets, other2->sets);
8718 res->msets = sRefSet_union (res->msets, other2->msets);
8719 res->uses = sRefSet_union (res->uses, other2->uses);
8727 ** Reports errors is s is not defined.
8731 exprNode_addUse (exprNode e, sRef s)
8733 if (exprNode_isDefined (e))
8735 e->uses = sRefSet_insert (e->uses, s);
8740 exprNode_checkUse (exprNode e, sRef s, fileloc loc)
8742 if (sRef_isKnown (s) && !sRef_isConst (s))
8745 ** need to check all outer types are useable
8748 DPRINTF (("Check use: %s / %s",
8749 exprNode_unparse (e), sRef_unparse (s)));
8751 exprNode_addUse (e, s);
8753 if (!context_inProtectVars ())
8756 ** only report the deepest error
8759 sRef errorRef = sRef_undefined;
8760 sRef lastRef = sRef_undefined;
8761 bool deadRef = FALSE;
8762 bool unuseable = FALSE;
8763 bool errorMaybe = FALSE;
8765 while (sRef_isValid (s) && sRef_isKnown (s))
8767 ynm readable = sRef_isReadable (s);
8769 if (!(ynm_toBoolStrict (readable)))
8771 if (ynm_isMaybe (readable))
8775 deadRef = sRef_isPossiblyDead (errorRef);
8776 unuseable = sRef_isUnuseable (errorRef);
8783 deadRef = sRef_isDead (errorRef);
8784 unuseable = sRef_isUnuseable (errorRef);
8788 if (!sRef_isPartial (s))
8790 sRef_setDefined (s, fileloc_undefined);
8794 s = sRef_getBaseSafe (s);
8797 if (sRef_isValid (errorRef))
8799 if (sRef_isValid (lastRef) && sRef_isField (lastRef)
8800 && sRef_isPointer (errorRef))
8807 if (sRef_isThroughArrayFetch (errorRef))
8810 (FLG_STRICTUSERELEASED,
8811 message ("%q %q may be used after being released",
8812 sRef_unparseKindNamePlain (errorRef),
8813 sRef_unparse (errorRef)),
8816 sRef_showRefKilled (errorRef);
8818 if (sRef_isKept (errorRef))
8820 sRef_clearAliasState (errorRef, loc);
8826 DPRINTF (("HERE: %s", sRef_unparse (errorRef)));
8830 message ("%q %q %qused after being released",
8831 sRef_unparseKindNamePlain (errorRef),
8832 sRef_unparse (errorRef),
8833 cstring_makeLiteral (errorMaybe
8837 sRef_showRefKilled (errorRef);
8839 if (sRef_isKept (errorRef))
8841 sRef_clearAliasState (errorRef, loc);
8850 message ("%q %q%qused in inconsistent state",
8851 sRef_unparseKindName (errorRef),
8852 sRef_unparseOpt (errorRef),
8853 cstring_makeLiteral (errorMaybe ? "may be " : "")),
8856 sRef_showStateInconsistent (errorRef);
8861 DPRINTF (("HERE: %s", sRef_unparse (errorRef)));
8865 message ("%q %q%qused before definition",
8866 sRef_unparseKindName (errorRef),
8867 sRef_unparseOpt (errorRef),
8868 cstring_makeLiteral (errorMaybe ? "may be " : "")),
8872 sRef_setDefined (errorRef, loc);
8874 if (sRef_isAddress (errorRef))
8876 sRef_setDefined (sRef_getRootBase (errorRef), loc);
8878 } /* end is error */
8886 checkSafeUse (exprNode e, sRef s)
8888 if (exprNode_isDefined (e) && sRef_isKnown (s))
8890 e->uses = sRefSet_insert (e->uses, s);
8895 exprNode_checkSetAny (exprNode e, /*@dependent@*/ cstring name)
8897 if (exprNode_isDefined (e))
8899 e->sets = sRefSet_insert (e->sets, sRef_makeUnconstrained (name));
8904 exprNode_checkSet (exprNode e, sRef s)
8906 sRef defines = sRef_undefined;
8908 if (sRef_isValid (s) && !sRef_isNothing (s))
8910 uentry ue = sRef_getBaseUentry (s);
8912 if (uentry_isValid (ue))
8914 uentry_setLset (ue);
8917 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
8919 voptgenerror (FLG_USEDEF,
8920 message ("Attempt to set unuseable storage: %q",
8925 if (sRef_isMeaningful (s))
8928 if (sRef_isDead (s))
8930 sRef base = sRef_getBaseSafe (s);
8932 if (sRef_isValid (base)
8933 && sRef_isDead (base))
8935 sRef_setPartial (s, exprNode_loc (e));
8938 defines = s; /* okay - modifies for only param */
8940 else if (sRef_isPartial (s))
8942 sRef eref = exprNode_getSref (e);
8944 if (!sRef_isPartial (eref))
8947 ** should do something different here???
8950 sRef_setDefinedComplete (eref, exprNode_loc (e));
8954 sRef_setPartialDefinedComplete (eref, exprNode_loc (e));
8957 if (sRef_isMeaningful (eref))
8966 else if (sRef_isAllocated (s))
8968 sRef eref = exprNode_getSref (e);
8971 if (!sRef_isAllocated (eref))
8973 sRef_setDefinedComplete (eref, exprNode_loc (e));
8977 sRef base = sRef_getBaseSafe (eref);
8979 if (sRef_isValid (base))
8981 sRef_setPdefined (base, exprNode_loc (e));
8989 sRef_setDefinedNCComplete (s, exprNode_loc (e));
8994 else /* not meaningful...but still need to insert it */
9000 if (exprNode_isDefined (e) && sRef_isValid (defines))
9002 e->sets = sRefSet_insert (e->sets, defines);
9007 exprNode_checkMSet (exprNode e, sRef s)
9009 if (sRef_isValid (s) && !sRef_isNothing (s))
9011 uentry ue = sRef_getBaseUentry (s);
9013 if (uentry_isValid (ue))
9015 uentry_setLset (ue);
9018 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
9020 voptgenerror (FLG_USEDEF,
9021 message ("Attempt to set unuseable storage: %q", sRef_unparse (s)),
9025 if (sRef_isMeaningful (s))
9027 sRef_setDefinedComplete (s, exprNode_loc (e));
9030 if (exprNode_isDefined (e))
9032 e->msets = sRefSet_insert (e->msets, s);
9038 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode fcn, uentryList params, exprNodeList args)
9040 checkAnyCall (fcn, cstring_undefined, params, args,
9041 FALSE, sRefSet_undefined, FALSE, 0);
9045 checkOneArg (uentry ucurrent, /*@notnull@*/ exprNode current,
9046 /*@dependent@*/ exprNode fcn, bool isSpec, int argno, int totargs)
9050 if (uentry_isYield (ucurrent))
9052 sRef_setDefined (exprNode_getSref (current), exprNode_loc (current));
9053 exprNode_checkSet (current, current->sref);
9057 if (uentry_isSefParam (ucurrent))
9059 sRefSet sets = current->sets;
9060 sRef ref = exprNode_getSref (current);
9062 if (sRef_isMacroParamRef (ref))
9064 uentry ue = sRef_getUentry (ref);
9066 if (!uentry_isSefParam (ue))
9071 ("Parameter %d to %s is declared sef, but "
9072 "the argument is a macro parameter declared "
9074 argno, exprNode_unparse (fcn),
9075 exprNode_unparse (current)),
9076 exprNode_loc (current));
9080 if (!sRefSet_isEmpty (sets))
9082 sRefSet reported = sRefSet_undefined;
9084 sRefSet_realElements (current->sets, el)
9086 if (sRefSet_isSameNameMember (reported, el))
9088 ; /* don't report again */
9092 if (sRef_isUnconstrained (el))
9097 ("Parameter %d to %s is declared sef, but "
9098 "the argument calls unconstrained function %s "
9099 "(no guarantee it will not modify something): %s",
9100 argno, exprNode_unparse (fcn),
9101 sRef_unconstrainedName (el),
9102 exprNode_unparse (current)),
9103 exprNode_loc (current));
9110 ("Parameter %d to %s is declared sef, but "
9111 "the argument may modify %q: %s",
9112 argno, exprNode_unparse (fcn),
9114 exprNode_unparse (current)),
9115 exprNode_loc (current));
9118 } end_sRefSet_realElements;
9122 checkPassTransfer (current, ucurrent, isSpec, fcn, argno, totargs);
9123 exprNode_mergeUSs (fcn, current);
9128 checkAnyCall (/*@dependent@*/ exprNode fcn,
9129 /*@dependent@*/ cstring fname,
9132 bool hasMods, sRefSet mods,
9137 int nargs = exprNodeList_size (args);
9142 ** concat all args ud's to f, add each arg sref as a use unless
9143 ** it was specified as "out", in which case it is a def.
9146 uentryList_reset (pn);
9151 ** if paramn is only or unique, no other arg may alias argn
9154 exprNodeList_elements (args, current)
9158 if (exprNode_isDefined (current))
9160 if ((!uentryList_isUndefined (pn) && !uentryList_isFinished (pn)))
9162 uentry ucurrent = uentryList_current (pn);
9164 if (specialArgs == 0
9165 || (paramno < specialArgs))
9167 checkOneArg (ucurrent, current, fcn, isSpec, paramno, nargs);
9169 if (context_maybeSet (FLG_ALIASUNIQUE))
9171 if (uentry_isOnly (ucurrent)
9172 || uentry_isUnique (ucurrent))
9174 checkUniqueParams (fcn, current, args,
9180 else /* uentry is undefined */
9182 if (specialArgs == 0)
9184 exprNode_checkUseParam (current);
9187 exprNode_mergeUSs (fcn, current);
9190 uentryList_advanceSafe (pn);
9191 } end_exprNodeList_elements;
9197 sRefSet_allElements (mods, s)
9200 sRef rb = sRef_getRootBase (s);
9202 if (sRef_isGlobal (rb))
9204 context_usedGlobal (rb);
9207 fb = sRef_fixBaseParam (s, args);
9209 if (!sRef_isMacroParamRef (fb))
9211 if (sRef_isNothing (fb))
9217 if (sRef_isValid (fb))
9219 uentry ue = sRef_getBaseUentry (s);
9221 if (uentry_isValid (ue))
9223 uentry_setLset (ue);
9227 fcn->sets = sRefSet_insert (fcn->sets, fb);
9230 sRef_clearDerivedComplete (s);
9231 } end_sRefSet_allElements;
9237 if (context_hasMods ())
9239 if (context_maybeSet (FLG_MODUNCON))
9243 message ("Undetected modification possible "
9244 "from call to unconstrained function %s: %s",
9246 exprNode_unparse (fcn)),
9247 exprNode_loc (fcn));
9252 if (context_maybeSet (FLG_MODUNCONNOMODS)
9253 && !(context_inIterDef () || context_inIterEnd ()))
9256 (FLG_MODUNCONNOMODS,
9257 message ("Undetected modification possible "
9258 "from call to unconstrained function %s: %s",
9260 exprNode_unparse (fcn)),
9261 exprNode_loc (fcn));
9265 exprNode_checkSetAny (fcn, fname);
9269 void exprNode_checkUseParam (exprNode current)
9271 if (exprNode_isDefined (current))
9273 exprNode_checkUse (current, current->sref, current->loc);
9278 checkNumerics (ctype tr1, ctype tr2, ctype te1, ctype te2,
9279 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
9284 if (!ctype_match (tr1, tr2))
9286 if ((ctype_isRealInt (tr1) || ctype_isReal (tr1)) &&
9287 (ctype_isRealInt (tr2) || ctype_isReal (tr2)))
9295 message ("Incompatible types for %s (%s, %s): %s %s %s",
9297 ctype_unparse (te1),
9298 ctype_unparse (te2),
9299 exprNode_unparse (e1), lltok_unparse (op),
9300 exprNode_unparse (e2)),
9303 ret = ctype_unknown;
9307 if (ctype_isForceRealNumeric (&tr1) && ctype_isForceRealNumeric (&tr2))
9309 ret = ctype_resolveNumerics (tr1, tr2);
9311 else if (!context_msgStrictOps ())
9313 if (ctype_isPointer (tr1))
9315 if (ctype_isPointer (tr2) && !exprNode_isNullValue (e2))
9319 else if (ctype_isInt (tr2))
9325 ret = ctype_unknown;
9328 else if (ctype_isPointer (tr2))
9330 if (ctype_isPointer (tr1))
9334 else if (ctype_isInt (tr1))
9340 ret = ctype_unknown;
9345 ret = ctype_resolveNumerics (tr1, tr2);
9350 int opid = lltok_getTok (op);
9351 bool comparop = (opid == EQ_OP || opid == NE_OP
9352 || opid == TLT || opid == TGT
9353 || opid == LE_OP || opid == GE_OP);
9355 if (!ctype_isNumeric (tr1) && !ctype_isNumeric (tr2))
9358 && ((ctype_isEnum (tr1) && ctype_isEnum (tr2))
9359 || (ctype_isBool (tr1) && ctype_isBool (tr2))
9360 || (ctype_isChar (tr1) && ctype_isChar (tr2))))
9366 if (ctype_sameName (te1, te2))
9370 message ("Operands of %s are non-numeric (%t): %s %s %s",
9371 lltok_unparse (op), te1,
9372 exprNode_unparse (e1), lltok_unparse (op),
9373 exprNode_unparse (e2)),
9380 message ("Operands of %s are non-numerics (%t, %t): %s %s %s",
9381 lltok_unparse (op), te1, te2,
9382 exprNode_unparse (e1), lltok_unparse (op),
9383 exprNode_unparse (e2)),
9388 else if (!ctype_isNumeric (tr1))
9392 message ("Right operand of %s is non-numeric (%t): %s %s %s",
9393 lltok_unparse (op), te1,
9394 exprNode_unparse (e1), lltok_unparse (op),
9395 exprNode_unparse (e2)),
9400 if (!ctype_isNumeric (tr2))
9404 message ("Left operand of %s is non-numeric (%t): %s %s %s",
9405 lltok_unparse (op), te2,
9406 exprNode_unparse (e1), lltok_unparse (op),
9407 exprNode_unparse (e2)),
9412 ret = ctype_unknown;
9420 abstractOpError (ctype tr1, ctype tr2, lltok op,
9421 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
9422 fileloc loc1, fileloc loc2)
9424 if (ctype_isRealAbstract (tr1) && ctype_isRealAbstract (tr2))
9426 if (ctype_match (tr1, tr2))
9430 message ("Operands of %s are abstract type (%t): %s %s %s",
9431 lltok_unparse (op), tr1,
9432 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
9439 message ("Operands of %s are abstract types (%t, %t): %s %s %s",
9440 lltok_unparse (op), tr1, tr2,
9441 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
9445 else if (ctype_isRealAbstract (tr1))
9449 message ("Left operand of %s is abstract type (%t): %s %s %s",
9450 lltok_unparse (op), tr1,
9451 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
9456 if (ctype_isRealAbstract (tr2))
9460 message ("Right operand of %s is abstract type (%t): %s %s %s",
9461 lltok_unparse (op), tr2,
9462 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
9471 ** requies e1 and e2 and not error exprNode's.
9475 ** If e1 is a component of an abstract type, and e2 is mutable and client-visible,
9476 ** the rep of the abstract type is exposed.
9478 ** The order is very important:
9480 ** check rep expose (move into check transfer)
9486 ** This isn't really a sensible procedure, but the indententation
9487 ** was getting too deep.
9491 checkOneRepExpose (sRef ysr, sRef base,
9492 /*@notnull@*/ exprNode e1,
9493 /*@notnull@*/ exprNode e2, ctype ct,
9496 if (!(sRef_isOnly (ysr) || sRef_isKeep (ysr)
9497 || sRef_isOwned (ysr) || sRef_isExposed (ysr)))
9499 if (sRef_isAnyParam (base) && !sRef_isExposed (base))
9501 if (sRef_isIReference (ysr))
9503 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
9508 ("Assignment of mutable component of parameter %q "
9509 "to component of abstract "
9510 "type %s exposes rep: %s = %s",
9511 sRef_unparse (base),
9513 exprNode_unparse (e1), exprNode_unparse (e2)),
9521 ("Assignment of mutable component of parameter %q "
9522 "(through alias %q) to component of abstract "
9523 "type %s exposes rep: %s = %s",
9524 sRef_unparse (base),
9525 sRef_unparse (e2->sref),
9527 exprNode_unparse (e1), exprNode_unparse (e2)),
9533 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
9537 message ("Assignment of mutable parameter %q "
9538 "to component of abstract type %s "
9539 "exposes rep: %s = %s",
9540 sRef_unparse (base),
9542 exprNode_unparse (e1),
9543 exprNode_unparse (e2)),
9550 message ("Assignment of mutable parameter %q "
9551 "(through alias %q) to "
9552 "component of abstract type %s exposes "
9554 sRef_unparse (base),
9555 sRef_unparse (e2->sref),
9557 exprNode_unparse (e1),
9558 exprNode_unparse (e2)),
9564 if (sRef_isGlobal (s2b))
9566 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
9570 message ("Assignment of global %q "
9572 "abstract type %s exposes rep: %s = %s",
9573 sRef_unparse (base),
9575 exprNode_unparse (e1), exprNode_unparse (e2)),
9582 message ("Assignment of global %q (through alias %q) "
9584 "abstract type %s exposes rep: %s = %s",
9585 sRef_unparse (base),
9586 sRef_unparse (e2->sref),
9588 exprNode_unparse (e1), exprNode_unparse (e2)),
9596 doAssign (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, bool isInit)
9598 if (ctype_isRealFunction (exprNode_getType (e1))
9599 && !ctype_isRealPointer (exprNode_getType (e1)))
9603 message ("Invalid left-hand side of assignment (function type %s): %s",
9604 ctype_unparse (exprNode_getType (e1)),
9605 exprNode_unparse (e1)),
9609 if (context_getFlag (FLG_ASSIGNEXPOSE) && ctype_isMutable (e2->typ))
9611 ctype t2 = exprNode_getType (e2);
9612 sRef sr = sRef_getRootBase (e1->sref);
9613 ctype ct = sRef_getType (sr);
9615 if (ctype_isAbstract (t2)
9616 && !(uentry_isMutableDatatype (usymtab_getTypeEntry (ctype_typeId (t2)))))
9618 /* it is immutable, okay to reference */
9622 if (ctype_isAbstract (ct) && sRef_isIReference (e1->sref))
9624 sRef s2b = sRef_getRootBase (e2->sref);
9626 sRef s1b = sRef_getRootBase (s1);
9629 aliases = usymtab_canAlias (e2->sref);
9631 if (!sRef_similar (s2b, s1b)
9632 && !sRef_isExposed (s1)
9633 && !(sRef_isOnly (s2b) || sRef_isKeep (s2b) || sRef_isExposed (s2b)))
9635 if (sRef_isAnyParam (s2b) && !sRef_isOnly (s2b)
9636 && !sRef_isOwned (s2b) && !sRef_isKeep (s2b)
9637 && !sRef_isExposed (s2b))
9639 if (sRef_isIReference (e2->sref))
9644 ("Assignment of mutable component of parameter %q "
9645 "to component of abstract type %s exposes rep: %s = %s",
9648 exprNode_unparse (e1), exprNode_unparse (e2)),
9655 message ("Assignment of mutable parameter %q to "
9656 "component of abstract type %s exposes rep: %s = %s",
9659 exprNode_unparse (e1), exprNode_unparse (e2)),
9664 if (sRef_isGlobal (s2b))
9668 message ("Assignment of global %q to component of "
9669 "abstract type %s exposes rep: %s = %s",
9672 exprNode_unparse (e1), exprNode_unparse (e2)),
9676 sRefSet_realElements (aliases, ysr)
9678 sRef base = sRef_getRootBase (ysr);
9680 if (sRef_similar (ysr, s2b) || sRef_similar (s1b, base)
9681 || sRef_sameName (base, s1b))
9683 ; /* error already reported or same sref */
9687 checkOneRepExpose (ysr, base, e1, e2, ct, s2b);
9689 } end_sRefSet_realElements;
9691 sRefSet_free (aliases);
9698 ** function variables don't really work...
9701 if (!ctype_isFunction (ctype_realType (e2->typ)))
9705 checkInitTransfer (e1, e2);
9709 checkAssignTransfer (e1, e2);
9714 sRef fref = e2->sref;
9716 sRef_setDefState (e1->sref, sRef_getDefState (fref), e1->loc);
9717 sRef_setNullState (e1->sref, sRef_getNullState (fref), e1->loc);
9719 /* Need to typecheck the annotation on the parameters */
9721 if (ctype_isRealFunction (e1->typ)) {
9722 uentryList e1p = ctype_argsFunction (ctype_realType (e1->typ));
9723 uentryList e2p = ctype_argsFunction (ctype_realType (e2->typ));
9725 if (!uentryList_isMissingParams (e1p)
9726 && !uentryList_isMissingParams (e2p)
9727 && uentryList_size (e1p) > 0) {
9728 if (uentryList_size (e1p) == uentryList_size (e2p)) {
9731 uentryList_elements (e1p, el1) {
9734 el2 = uentryList_getN (e2p, n);
9736 uentry_checkMatchParam (el1, el2, n, e2);
9737 } end_uentryList_elements;
9743 if (isInit && sRef_isGlobal (e1->sref))
9749 updateAliases (e1, e2);
9751 // updateEnvironment (e1, e2);
9755 checkMacroParen (exprNode e)
9757 if (exprNode_isError (e) || e->kind == XPR_CAST)
9763 if (sRef_isUnsafe (e->sref) && !exprNode_isInParens (e))
9767 message ("Macro parameter used without parentheses: %s",
9768 exprNode_unparse (e)),
9775 reflectNullTest (/*@notnull@*/ exprNode e, bool isnull)
9779 e->guards = guardSet_addTrueGuard (e->guards, e->sref);
9783 e->guards = guardSet_addFalseGuard (e->guards, e->sref);
9790 ** if e2 is a parameter or global derived location which
9791 ** can be modified (that is, e2 is a mutable abstract type,
9792 ** or a derived pointer), then e1 can alias e2.
9794 ** e1 can alias everything which e2 can alias.
9796 ** Also, if e1 is guarded, remove from guard sets!
9799 static void updateAliases (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2)
9801 if (!context_inProtectVars ())
9804 ** depends on types of e1 and e2
9809 ctype t1 = exprNode_getType (e1);
9811 /* handle pointer sRefs, record fields, arrays, etc... */
9813 if (!ctype_isRealSU (t1))
9815 sRef_copyRealDerivedComplete (s1, s2);
9818 if (ctype_isMutable (t1) && sRef_isKnown (s1))
9820 usymtab_clearAlias (s1);
9821 usymtab_addMustAlias (s1, s2);
9824 if (sRef_possiblyNull (s1) && usymtab_isGuarded (s1))
9826 usymtab_unguard (s1);
9831 exprNode exprNode_updateLocation (/*@returned@*/ exprNode e, /*@temp@*/ fileloc loc)
9833 if (exprNode_isDefined (e))
9835 e->loc = fileloc_update (e->loc, loc);
9839 e = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
9845 static void checkUniqueParams (exprNode fcn,
9846 /*@notnull@*/ exprNode current,
9848 int paramno, uentry ucurrent)
9851 sRef thisref = exprNode_getSref (current);
9854 ** Check if any argument could match this argument.
9857 exprNodeList_elements (args, icurrent)
9861 if (iparamno != paramno)
9863 sRef sr = exprNode_getSref (icurrent);
9865 if (sRef_similarRelaxed (thisref, sr))
9867 if (!sRef_isConst (thisref) && !sRef_isConst (sr))
9872 ("Parameter %d (%s) to function %s is declared %s but "
9873 "is aliased by parameter %d (%s)",
9875 exprNode_unparse (current),
9876 exprNode_unparse (fcn),
9877 alkind_unparse (uentry_getAliasKind (ucurrent)),
9878 iparamno, exprNode_unparse (icurrent)),
9884 sRefSet aliases = usymtab_canAlias (sr);
9886 sRefSet_allElements (aliases, asr)
9888 if (ctype_isUnknown (sRef_getType (thisref)))
9890 sRef_setType (thisref, uentry_getType (ucurrent));
9893 if (sRef_similarRelaxed (thisref, asr))
9895 if (sRef_isExternal (asr))
9897 if (sRef_isLocalState (thisref))
9903 sRef base = sRef_getRootBase (asr);
9905 if (!sRef_similar (sRef_getBase (asr), thisref))
9907 if (sRef_isUnique (base) || sRef_isOnly (base)
9908 || sRef_isKept (base)
9909 || (sRef_isAddress (asr) && sRef_isLocalVar (base))
9910 || (sRef_isAddress (thisref)
9911 && sRef_isLocalVar (sRef_getRootBase (thisref))))
9913 ; /* okay, no error */
9918 (FLG_MAYALIASUNIQUE,
9920 ("Parameter %d (%s) to function %s is declared %s but "
9921 "may be aliased externally by parameter %d (%s)",
9923 exprNode_unparse (current),
9924 exprNode_unparse (fcn),
9925 alkind_unparse (uentry_getAliasKind (ucurrent)),
9926 iparamno, exprNode_unparse (icurrent)),
9937 ("Parameter %d (%s) to function %s is declared %s but "
9938 "is aliased externally by parameter %d (%s) through "
9941 exprNode_unparse (current),
9942 exprNode_unparse (fcn),
9943 alkind_unparse (uentry_getAliasKind (ucurrent)),
9944 iparamno, exprNode_unparse (icurrent),
9945 sRef_unparse (asr)),
9949 } end_sRefSet_allElements;
9950 sRefSet_free (aliases);
9953 } end_exprNodeList_elements;
9956 long exprNode_getLongValue (exprNode e) {
9959 if (exprNode_hasValue (e)
9960 && multiVal_isInt (exprNode_getValue (e)))
9962 value = multiVal_forceInt (exprNode_getValue (e));
9972 fileloc exprNode_getfileloc (exprNode p_e)
9974 if (exprNode_isDefined (p_e) )
9975 return fileloc_copy ( p_e->loc );
9977 return fileloc_undefined;
9980 fileloc exprNode_getNextSequencePoint (exprNode e)
9983 ** Returns the location of the sequence point following e.
9985 ** Only works for statements (for now).
9988 if (exprNode_isDefined (e) && e->kind == XPR_STMT) {
9989 lltok t = exprData_getUopTok (e->edata);
9990 return lltok_getLoc (t);
9993 // llcontbug (message ("Cannot get next sequence point: %s", exprNode_unparse (e)));
9994 return fileloc_undefined;
10001 exprNode exprNode_fakeCopy (exprNode e)
10003 /*@-temptrans@*/ /*@-retalias@*/
10005 /*@=temptrans@*/ /*@=retalias@*/
10008 exprNode exprNode_createNew(ctype c)
10012 ret = exprNode_createPlain (c);