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);
46 static exprNode exprNode_fakeCopy (exprNode p_e) /*@*/ ;
47 static exprNode exprNode_statementError (/*@only@*/ exprNode p_e);
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;
110 ** must occur after library has been read
113 void exprNode_initMod (void)
114 /*@globals undef regArg, undef outArg, undef outStringArg,
115 undef csOnlyArg, undef csArg;
122 cstringType = ctype_unknown;
123 ctypeType = ctype_unknown;
124 filelocType = ctype_unknown;
126 defref = sRef_undefined;
128 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
130 cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
133 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
135 ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
138 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
140 filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
143 if (usymtab_existsGlob (cstring_makeLiteralTemp ("stdin")))
145 ue = usymtab_lookupGlob (cstring_makeLiteralTemp ("stdin"));
147 else /* define stdin */
149 ue = uentry_makeVariable (cstring_makeLiteralTemp ("stdin"),
151 fileloc_getBuiltin (),
153 uentry_setHasNameError (ue);
154 ue = usymtab_supGlobalEntryReturn (ue);
157 stdinRef = sRef_makePointer (uentry_getSref (ue));
159 if (usymtab_existsGlob (cstring_makeLiteralTemp ("stdout")))
161 ue = usymtab_lookupGlob (cstring_makeLiteralTemp ("stdout"));
165 ue = uentry_makeVariable (cstring_makeLiteralTemp ("stdout"),
167 fileloc_getBuiltin (),
169 uentry_setHasNameError (ue);
170 ue = usymtab_supGlobalEntryReturn (ue);
173 stdoutRef = sRef_makePointer (uentry_getSref (ue));
175 tmp = idDecl_create (cstring_undefined, qtype_create (ctype_unknown));
177 regArg = uentry_makeParam (tmp, PARAMUNKNOWN);
180 qtype_addQual (qtype_create (ctype_makePointer (ctype_unknown)),
183 outArg = uentry_makeParam (tmp, PARAMUNKNOWN);
185 idDecl_setTyp (tmp, qtype_addQual (qtype_create (ctype_string),
188 outStringArg = uentry_makeParam (tmp, PARAMUNKNOWN);
190 idDecl_setTyp (tmp, qtype_addQual (qtype_addQual (qtype_create (cstringType),
192 qual_createNull ()));
194 csOnlyArg = uentry_makeParam (tmp, PARAMUNKNOWN);
196 idDecl_setTyp (tmp, qtype_addQual (qtype_create (cstringType), qual_createNull ()));
197 csArg = uentry_makeParam (tmp, PARAMUNKNOWN);
203 exprNode_destroyMod (void)
204 /*@globals killed regArg, killed outArg, killed outStringArg,
205 killed mustExitNode, initMod @*/
209 uentry_free (regArg);
210 uentry_free (outArg);
211 uentry_free (outStringArg);
213 exprNode_free (mustExitNode);
220 static void exprNode_resetSref (/*@notnull@*/ exprNode e)
225 static exprNode exprNode_fakeCopy (exprNode e)
227 /*@-temptrans@*/ /*@-retalias@*/
229 /*@=temptrans@*/ /*@=retalias@*/
232 static bool isFlagKey (char key)
234 return (key == '-' || key == '+' || key == ' ' || key == '#');
237 static void exprNode_combineControl (/*@notnull@*/ exprNode ret,
238 /*@notnull@*/ exprNode ifclause,
239 /*@notnull@*/ exprNode elseclause)
241 ret->canBreak = ifclause->canBreak || elseclause->canBreak;
244 (ifclause->mustBreak || exprNode_mustEscape (ifclause))
245 && (elseclause->mustBreak || exprNode_mustEscape (elseclause));
247 ret->exitCode = exitkind_combine (ifclause->exitCode,
248 elseclause->exitCode);
253 ** For exprNode's returned by exprNode_effect.
256 static bool shallowKind (exprKind kind)
258 return (kind == XPR_STRINGLITERAL
259 || kind == XPR_NUMLIT
262 || kind == XPR_NODE);
266 exprNode_freeIniter (/*@only@*/ exprNode e)
268 if (!exprNode_isError (e))
273 sfree (e->edata->field);
277 exprNode_free (e->edata->op->b);
278 /*@-compdestroy@*/ sfree (e->edata->op); /*@=compdestroy@*/
282 llbug (message ("other: %s", exprNode_unparse (e)));
285 multiVal_free (e->val);
286 cstring_free (e->etext);
287 fileloc_free (e->loc);
288 sRefSet_free (e->uses);
289 sRefSet_free (e->sets);
290 sRefSet_free (e->msets);
291 guardSet_free (e->guards);
297 exprNode_freeShallow (/*@only@*/ exprNode e)
299 if (!exprNode_isError (e))
301 if (shallowKind (e->kind))
308 if (e->kind == XPR_EMPTY
309 || e->kind == XPR_BODY
310 || e->kind == XPR_STRINGLITERAL
311 || e->kind == XPR_NUMLIT
312 || e->kind == XPR_NODE
313 || e->kind == XPR_OFFSETOF
314 || e->kind == XPR_ALIGNOFT
315 || e->kind == XPR_ALIGNOF
316 || e->kind == XPR_SIZEOFT
317 || e->kind == XPR_SIZEOF)
319 /* don't free anything */
323 /* multiVal_free (e->val); */
324 cstring_free (e->etext);
325 fileloc_free (e->loc);
326 sRefSet_free (e->uses);
327 sRefSet_free (e->sets);
328 sRefSet_free (e->msets);
329 guardSet_free (e->guards);
330 exprData_freeShallow (e->edata, e->kind);
332 /*@-compdestroy@*/ sfree (e); /*@=compdestroy@*/
341 exprNode_free (exprNode e)
343 if (!exprNode_isError (e))
347 multiVal_free (e->val);
348 cstring_free (e->etext);
349 fileloc_free (e->loc);
350 sRefSet_free (e->uses);
351 sRefSet_free (e->sets);
352 sRefSet_free (e->msets);
353 guardSet_free (e->guards);
354 exprData_free (e->edata, e->kind);
364 exprNode_makeError ()
366 return exprNode_undefined;
369 static /*@out@*/ /*@only@*/ /*@notnull@*/ exprNode
372 exprNode ret = (exprNode) dmalloc (sizeof (*ret));
373 /* static int lastexpnodes = 0; */
378 if (nowalloc > maxalloc)
386 static /*@notnull@*/ /*@special@*/ exprNode
387 exprNode_createPlain (ctype c)
389 /*@post:isnull result->edata, result->loc, result->val, result->guards,
390 result->uses, result->sets, result->msets, result->etext @*/
393 exprNode e = exprNode_new ();
397 e->val = multiVal_undefined;
399 e->etext = cstring_undefined;
400 e->loc = fileloc_undefined;
401 e->guards = guardSet_undefined;
402 e->uses = sRefSet_undefined;
403 e->sets = sRefSet_undefined;
404 e->msets = sRefSet_undefined;
405 e->edata = exprData_undefined;
406 e->exitCode = XK_NEVERESCAPE;
408 e->mustBreak = FALSE;
409 e->isJumpPoint = FALSE;
413 /*@observer@*/ exprNode exprNode_makeMustExit (void)
415 if (exprNode_isUndefined (mustExitNode))
417 mustExitNode = exprNode_createPlain (ctype_unknown);
418 mustExitNode->exitCode = XK_MUSTEXIT;
425 static /*@notnull@*/ /*@special@*/ exprNode exprNode_create (ctype c)
427 /*@post:isnull result->edata, result->guards, result->val,
428 result->uses, result->sets, result->msets@*/
431 exprNode e = exprNode_createPlain (c);
432 e->loc = fileloc_copy (g_currentloc);
436 static /*@notnull@*/ /*@special@*/ exprNode exprNode_createUnknown (void)
438 /*@post:isnull result->edata, result->guards,
439 result->uses, result->sets, result->msets@*/
442 return (exprNode_create (ctype_unknown));
445 static /*@notnull@*/ /*@special@*/ exprNode
446 exprNode_createLoc (ctype c, /*@keep@*/ fileloc loc)
448 /*@post:isnull result->edata, result->guards, result->val,
449 result->uses, result->sets, result->msets@*/
452 exprNode e = exprNode_createPlain (c);
458 exprNode_copySets (/*@special@*/ /*@notnull@*/ exprNode ret, exprNode e)
459 /*@defines ret->guards, ret->uses, ret->sets, ret->msets@*/
461 if (exprNode_isDefined (e))
463 ret->guards = guardSet_copy (e->guards);
464 ret->uses = sRefSet_newCopy (e->uses);
465 ret->sets = sRefSet_newCopy (e->sets);
466 ret->msets = sRefSet_newCopy (e->msets);
470 ret->guards = guardSet_undefined;
471 ret->uses = sRefSet_undefined;
472 ret->sets = sRefSet_undefined;
473 ret->msets = sRefSet_undefined;
477 static /*@notnull@*/ /*@special@*/ exprNode
478 exprNode_createPartialLocCopy (exprNode e, /*@only@*/ fileloc loc)
480 /*@post:isnull result->edata, result->etext@*/
483 exprNode ret = exprNode_new ();
485 if (exprNode_isError (e))
487 ret->typ = ctype_unknown;
488 ret->val = multiVal_undefined;
490 ret->guards = guardSet_undefined;
491 ret->uses = sRefSet_undefined;
492 ret->sets = sRefSet_undefined;
493 ret->msets = sRefSet_undefined;
498 ret->val = multiVal_copy (e->val);
500 ret->guards = guardSet_copy (e->guards);
501 ret->uses = sRefSet_newCopy (e->uses);
502 ret->sets = sRefSet_newCopy (e->sets);
503 ret->msets = sRefSet_newCopy (e->msets);
506 ret->kind = XPR_EMPTY;
508 ret->etext = cstring_undefined;
509 ret->exitCode = XK_NEVERESCAPE;
510 ret->canBreak = FALSE;
511 ret->mustBreak = FALSE;
512 ret->isJumpPoint = FALSE;
513 ret->edata = exprData_undefined;
519 static /*@notnull@*/ /*@special@*/ exprNode
520 exprNode_createPartialCopy (exprNode e)
522 /*@post:isnull result->edata, result->etext@*/
525 return (exprNode_createPartialLocCopy (e, fileloc_copy (exprNode_loc (e))));
528 static /*@notnull@*/ /*@special@*/ exprNode
529 exprNode_createPartialNVCopy (exprNode e)
531 /*@post:isnull result->edata, result->etext, result->val @*/
534 exprNode ret = exprNode_new ();
536 if (exprNode_isError (e))
538 ret->typ = ctype_unknown;
539 ret->loc = fileloc_undefined;
540 ret->guards = guardSet_undefined;
541 ret->uses = sRefSet_undefined;
542 ret->sets = sRefSet_undefined;
543 ret->msets = sRefSet_undefined;
548 ret->loc = fileloc_copy (e->loc);
549 ret->guards = guardSet_copy (e->guards);
550 ret->uses = sRefSet_newCopy (e->uses);
551 ret->sets = sRefSet_newCopy (e->sets);
552 ret->msets = sRefSet_newCopy (e->msets);
555 ret->val = multiVal_undefined;
556 ret->kind = XPR_EMPTY;
558 ret->etext = cstring_undefined;
559 ret->exitCode = XK_NEVERESCAPE;
560 ret->canBreak = FALSE;
561 ret->mustBreak = FALSE;
562 ret->isJumpPoint = FALSE;
563 ret->edata = exprData_undefined;
568 static /*@notnull@*/ /*@special@*/ exprNode
569 exprNode_createSemiCopy (exprNode e)
571 /*@post:isnull result->edata, result->etext, result->sets,
572 result->msets, result->uses, result->guards@*/
575 if (exprNode_isError (e))
577 return exprNode_createPlain (ctype_unknown);
581 exprNode ret = exprNode_new ();
584 ret->val = multiVal_copy (e->val);
585 ret->loc = fileloc_copy (e->loc);
586 ret->guards = guardSet_undefined;
587 ret->uses = sRefSet_undefined;
588 ret->sets = sRefSet_undefined;
589 ret->msets = sRefSet_undefined;
591 ret->kind = XPR_EMPTY;
593 ret->etext = cstring_undefined;
594 ret->exitCode = XK_NEVERESCAPE;
595 ret->canBreak = FALSE;
596 ret->mustBreak = FALSE;
597 ret->isJumpPoint = FALSE;
598 ret->edata = exprData_undefined;
605 exprNode_isNullValue (exprNode e)
607 if (exprNode_isDefined (e))
609 multiVal m = exprNode_getValue (e);
611 if (multiVal_isInt (m))
613 return (multiVal_forceInt (m) == 0);
621 exprNode_isUnknownConstant (/*@notnull@*/ exprNode e)
623 while (e->kind == XPR_PARENS)
625 e = exprData_getUopNode (e->edata);
626 llassert (exprNode_isDefined (e));
629 if (e->kind == XPR_CONST)
631 multiVal m = exprNode_getValue (e);
633 if (multiVal_isUnknown (m))
643 exprNode_numLiteral (ctype c, /*@temp@*/ cstring t,
644 /*@only@*/ fileloc loc, long val)
646 exprNode e = exprNode_createLoc (c, loc);
648 e->kind = XPR_NUMLIT;
650 llassert (multiVal_isUndefined (e->val));
651 e->val = multiVal_makeInt (val);
652 e->edata = exprData_makeLiteral (cstring_copy (t));
656 e->sref = sRef_makeUnknown ();
657 sRef_setDefNull (e->sref, e->loc);
660 DPRINTF (("Num lit: %s / %s", exprNode_unparse (e), ctype_unparse (exprNode_getType (e))));
665 exprNode_charLiteral (char c, cstring text, /*@only@*/ fileloc loc)
667 exprNode e = exprNode_createLoc (ctype_char, loc);
669 if (context_getFlag (FLG_CHARINTLITERAL))
671 e->typ = ctype_makeConj (ctype_char, ctype_int);
674 e->kind = XPR_NUMLIT;
675 e->val = multiVal_makeChar (c);
677 e->edata = exprData_makeLiteral (cstring_copy (text));
682 exprNode_floatLiteral (double d, ctype ct, cstring text, /*@only@*/ fileloc loc)
684 exprNode e = exprNode_createLoc (ct, loc);
686 e->kind = XPR_NUMLIT;
687 e->val = multiVal_makeDouble (d);
688 e->edata = exprData_makeLiteral (cstring_copy (text));
692 multiVal exprNode_getValue (exprNode e)
694 while (exprNode_isInParens (e)) {
695 if (e->edata != NULL) {
696 e = exprData_getUopNode (e->edata);
702 if (exprNode_isDefined (e)) {
705 return multiVal_undefined;
710 exprNode_stringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
712 exprNode e = exprNode_createLoc (ctype_string, loc);
713 int len = cstring_length (t) - 2;
714 char *ts = cstring_toCharsSafe (t);
715 char *s = cstring_toCharsSafe (cstring_create (len + 1));
717 if (context_getFlag (FLG_STRINGLITERALLEN))
719 if (len > context_getValue (FLG_STRINGLITERALLEN))
721 voptgenerror (FLG_STRINGLITERALLEN,
723 ("String literal length (%d) exceeds maximum "
726 context_getValue (FLG_STRINGLITERALLEN),
732 strncpy (s, ts+1, size_fromInt (len));
736 e->kind = XPR_STRINGLITERAL;
737 e->val = multiVal_makeString (cstring_fromCharsO (s));
738 e->edata = exprData_makeLiteral (t);
739 e->sref = sRef_makeType (ctype_string);
741 if (context_getFlag (FLG_READONLYSTRINGS))
743 sRef_setAliasKind (e->sref, AK_STATIC, fileloc_undefined);
744 sRef_setExKind (e->sref, XO_OBSERVER, loc);
748 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
751 return (e); /* s released */
754 exprNode exprNode_fromUIO (cstring c)
756 fileloc loc = context_getSaveLocation ();
757 exprNode e = exprNode_createPlain (ctype_unknown);
761 if (fileloc_isUndefined (loc))
763 loc = fileloc_copy (g_currentloc);
766 e->loc = loc; /* save loc was mangled */
769 if (usymtab_exists (c))
771 uentry ue = usymtab_lookupEither (c);
773 if (uentry_isDatatype (ue)
774 && uentry_isSpecified (ue))
777 (message ("%q: Specified datatype %s used in code, but not defined. "
778 "(Cannot continue reasonably from this error.)",
779 fileloc_unparse (e->loc), c));
787 llassertprint (!usymtab_exists (c), ("Entry exists: %s", c));
790 ** was supercedeGlobalEntry...is this better?
793 if (!context_inIterEnd ())
795 if (context_inMacro ())
797 if (context_getFlag (FLG_UNRECOG))
801 message ("Unrecognized identifier in macro definition: %s", c), e->loc);
805 flagcode_recordSuppressed (FLG_UNRECOG);
811 (FLG_UNRECOG, message ("Unrecognized identifier: %s", c),
816 e->edata = exprData_makeId (uentry_makeUnrecognized (c, fileloc_copy (loc)));
818 /* No alias errors for unrecognized identifiers */
819 sRef_setAliasKind (e->sref, AK_ERROR, loc);
824 exprNode exprNode_createId (/*@observer@*/ uentry c)
826 if (uentry_isValid (c))
828 exprNode e = exprNode_new ();
830 e->typ = uentry_getType (c);
832 if (uentry_isFunction (c)
833 && !sRef_isLocalVar (uentry_getSref (c)))
835 e->sref = sRef_undefined;
839 e->sref = uentry_getSref (c);
842 if (sRef_isStateUnknown (e->sref) && uentry_isNonLocal (c))
844 sRef_setDefined (e->sref, fileloc_undefined);
848 ** yoikes! leaving this out was a heinous bug...that would have been
849 ** caught if i had lclint working first. gag!
852 e->etext = cstring_undefined;
854 if (uentry_isEitherConstant (c))
857 e->val = multiVal_copy (uentry_getConstantValue (c));
862 e->val = multiVal_unknown ();
865 e->edata = exprData_makeId (c);
866 e->loc = context_getSaveLocation ();
868 if (fileloc_isUndefined (e->loc))
870 fileloc_free (e->loc);
871 e->loc = fileloc_copy (g_currentloc);
874 e->guards = guardSet_new ();
875 e->sets = sRefSet_new ();
876 e->msets = sRefSet_new ();
877 e->uses = sRefSet_new ();
879 /*> missing fields, detected by lclint <*/
880 e->exitCode = XK_NEVERESCAPE;
881 e->isJumpPoint = FALSE;
883 e->mustBreak = FALSE;
889 return exprNode_createUnknown ();
893 /*@notnull@*/ exprNode
894 exprNode_fromIdentifier (/*@observer@*/ uentry c)
898 if (context_justPopped ()) /* watch out! c could be dead */
900 uentry ce = usymtab_lookupSafe (LastIdentifier ());
902 if (uentry_isValid (ce))
908 llbuglit ("Looks like Aunt Millie forgot to walk to dog again.");
912 ret = exprNode_fromIdentifierAux (c);
918 static /*@only@*/ /*@notnull@*/ exprNode
919 exprNode_fromIdentifierAux (/*@observer@*/ uentry c)
921 exprNode e = exprNode_createId (c);
924 uentry_setUsed (c, e->loc);
926 if (uentry_isVar (c) && sRef_isGlobal (sr))
928 checkGlobUse (c, FALSE, e);
935 exprNode_isZero (exprNode e)
937 if (exprNode_isDefined (e))
939 multiVal m = exprNode_getValue (e);
941 if (multiVal_isInt (m))
943 return (multiVal_forceInt (m) == 0);
951 exprNode_isNonNegative (exprNode e)
953 if (exprNode_isDefined (e))
955 multiVal m = exprNode_getValue (e);
957 if (multiVal_isInt (m))
959 return (multiVal_forceInt (m) >= 0);
967 ** a[x] - uses a but NOT a[]
968 ** result sref = a[] (set/use in assignment)
970 ** The syntax x[a] is also legal in C, and has the same
971 ** semantics. If ind is an array, and arr is an int, flip
976 exprNode_arrayFetch (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
979 ** error in arr, error propagates (no new messages)
980 ** error in ind, assume valid and continue
983 if (exprNode_isError (e1))
986 return (exprNode_makeError ());
992 ctype carr = exprNode_getType (e1);
993 ctype crarr = ctype_realType (carr);
996 ** this sets up funny aliasing, that leads to spurious
997 ** lclint errors. Hence, the i2 comments.
1000 if (!ctype_isRealArray (crarr)
1001 && ctype_isRealNumeric (crarr)
1002 && !exprNode_isError (e2)
1003 && ctype_isRealAP (exprNode_getType (e2))) /* fetch like 3[a] */
1008 carr = exprNode_getType (arr);
1009 crarr = ctype_realType (carr);
1017 if (sRef_possiblyNull (arr->sref))
1019 if (!usymtab_isGuarded (arr->sref))
1021 if (optgenerror (FLG_NULLDEREF,
1022 message ("Index of %s pointer %q: %s",
1023 sRef_nullMessage (arr->sref),
1024 sRef_unparse (arr->sref),
1025 exprNode_unparse (arr)),
1028 sRef_showNullInfo (arr->sref);
1030 /* suppress future messages */
1031 sRef_setNullError (arr->sref);
1036 if (exprNode_isError (ind))
1038 if ((ctype_isArrayPtr (crarr)
1039 && !ctype_isFunction (crarr))
1040 || ctype_isUnknown (carr))
1042 exprNode ret = exprNode_createPartialCopy (arr);
1044 if (ctype_isKnown (carr))
1046 ret->typ = ctype_baseArrayPtr (crarr);
1050 ret->typ = ctype_unknown;
1053 ret->sref = sRef_makeArrayFetch (arr->sref);
1055 ret->kind = XPR_FETCH;
1058 ** Because of funny aliasing (when arr and ind are
1059 ** flipped) spurious errors would be reported here.
1062 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1063 checkSafeUse (ret, arr->sref);
1068 voptgenerror (FLG_TYPE,
1069 message ("Array fetch from non-array (%t): %s[%s]", carr,
1070 exprNode_unparse (e1), exprNode_unparse (e2)),
1072 exprNode_free (arr);
1073 return (exprNode_makeError ());
1078 if (!ctype_isForceRealInt (&(ind->typ)))
1080 ctype rt = ctype_realType (ind->typ);
1082 if (ctype_isChar (rt))
1086 message ("Array fetch using non-integer, %t: %s[%s]",
1088 exprNode_unparse (e1), exprNode_unparse (e2)),
1091 else if (ctype_isEnum (rt))
1095 message ("Array fetch using non-integer, %t: %s[%s]",
1097 exprNode_unparse (e1), exprNode_unparse (e2)),
1104 message ("Array fetch using non-integer, %t: %s[%s]",
1106 exprNode_unparse (e1), exprNode_unparse (e2)),
1110 multiVal_free (ind->val);
1111 ind->val = multiVal_unknown ();
1114 if (ctype_isArrayPtr (crarr) && !ctype_isFunction (crarr))
1116 exprNode ret = exprNode_createSemiCopy (arr);
1117 multiVal m = exprNode_getValue (ind);
1119 ret->typ = ctype_baseArrayPtr (crarr);
1120 ret->kind = XPR_FETCH;
1122 if (multiVal_isInt (m))
1124 int i = (int) multiVal_forceInt (m);
1126 if (sRef_isValid (arr->sref)) {
1127 ret->sref = sRef_makeArrayFetchKnown (arr->sref, i);
1129 ret->sref = sRef_undefined;
1134 ret->sref = sRef_makeArrayFetch (arr->sref);
1137 ret->sets = sRefSet_realNewUnion (arr->sets, ind->sets);
1138 ret->msets = sRefSet_realNewUnion (arr->msets, ind->msets);
1139 ret->uses = sRefSet_realNewUnion (arr->uses, ind->uses);
1141 /* (see comment on spurious errors above) */
1142 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1144 exprNode_checkUse (ret, ind->sref, ind->loc);
1145 exprNode_checkUse (ret, arr->sref, arr->loc);
1151 if (ctype_isUnknown (carr))
1153 exprNode ret = exprNode_createPartialCopy (arr);
1155 ret->kind = XPR_FETCH;
1156 ret->typ = ctype_unknown;
1157 ret->sets = sRefSet_union (ret->sets, ind->sets);
1158 ret->msets = sRefSet_union (ret->msets, ind->msets);
1159 ret->uses = sRefSet_union (ret->uses, ind->uses);
1161 /* (see comment on spurious errors above) */
1162 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1164 exprNode_checkUse (ret, ind->sref, ind->loc);
1165 exprNode_checkUse (ret, arr->sref, arr->loc);
1172 message ("Array fetch from non-array (%t): %s[%s]", carr,
1173 exprNode_unparse (e1), exprNode_unparse (e2)),
1176 exprNode_free (arr);
1177 exprNode_free (ind);
1179 return (exprNode_makeError ());
1189 checkArgs (uentry fcn, /*@dependent@*/ exprNode f, ctype t,
1190 exprNodeList args, exprNode ret)
1192 return (checkArgsReal (fcn, f, ctype_argsFunction (t), args, FALSE, ret));
1196 ** checkPrintfArgs --- checks arguments for printf-like functions
1197 ** Arguments before ... have already been checked.
1198 ** The argument before the ... is a char *.
1199 ** argno is the format string argument.
1203 checkPrintfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1204 exprNodeList args, exprNode ret, int argno)
1207 ** the last argument before the elips is the format string
1212 int nargs = exprNodeList_size (args);
1213 uentryList params = uentry_getParams (fcn);
1217 ** These should be ensured by checkSpecialFunction
1220 llassert (uentryList_size (params) == argno + 1);
1221 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1223 a = exprNodeList_getN (args, argno - 1);
1224 formatloc = fileloc_copy (exprNode_loc (a));
1226 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1227 && exprNode_knownStringValue (a))
1229 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1230 char *code = format;
1233 nargs = exprNodeList_size (args);
1235 while ((code = strchr (code, '%')) != NULL)
1237 char *origcode = code;
1238 char key = *(++code);
1239 ctype modtype = ctype_int;
1240 bool modified = FALSE;
1242 fileloc_addColumn (formatloc, code - ocode);
1245 while (isFlagKey (key))
1248 fileloc_incColumn (formatloc);
1251 if (key == 'm') /* skipped in syslog */
1256 /* ignore field width */
1257 while (isdigit ((int) key) != 0)
1260 fileloc_incColumn (formatloc);
1263 /* ignore precision */
1267 fileloc_incColumn (formatloc);
1270 ** In printf, '*' means: read the next arg as an int for the
1271 ** field width. This seems to be missing from my copy of the
1272 ** standard x3.159-1989. Setion 4.9.6.1 refers to * (described
1273 ** later) but never does.
1278 ; /* don't do anything --- handle later */
1282 while (isdigit ((int) key) != 0)
1285 fileloc_incColumn (formatloc);
1292 modtype = ctype_sint; /* short */
1294 fileloc_incColumn (formatloc);
1296 else if (key == 'l' || key == 'L')
1298 modtype = ctype_lint; /* long */
1300 fileloc_incColumn (formatloc);
1307 /* now, key = type of conversion to apply */
1309 fileloc_incColumn (formatloc);
1317 message ("No argument corresponding to %q format "
1318 "code %d (%%%h): \"%s\"",
1319 uentry_getName (fcn),
1321 cstring_fromChars (format)),
1324 if (fileloc_isDefined (formatloc)
1325 && context_getFlag (FLG_SHOWCOL))
1327 llgenindentmsg (cstring_makeLiteral ("Corresponding format code"),
1335 a = exprNodeList_getN (args, i);
1338 if (!exprNode_isError (a))
1344 case '*': /* int argument for fieldwidth */
1345 expecttype = ctype_int;
1346 *(--code) = '%'; /* convert it for next code */
1347 fileloc_subColumn (formatloc, 1);
1348 /*@switchbreak@*/ break;
1351 expecttype = ctype_combine (ctype_uint, modtype);
1352 /*@switchbreak@*/ break;
1354 case 'i': /* int argument */
1356 expecttype = ctype_combine (ctype_int, modtype);
1357 /*@switchbreak@*/ break;
1359 case 'x': /* unsigned int */
1361 expecttype = ctype_combine (ctype_uint, modtype);
1362 /*@switchbreak@*/ break;
1368 case 'f': /* double */
1369 expecttype = ctype_combine (ctype_double, modtype);
1370 /*@switchbreak@*/ break;
1372 case 'c': /* int converted to char (check its a char?) */
1373 expecttype = ctype_makeConj (ctype_char, ctype_uchar);
1374 /*@switchbreak@*/ break;
1376 case 's': /* string */
1377 expecttype = ctype_string;
1378 /*@switchbreak@*/ break;
1381 while (((key = *(++code)) != ']')
1384 fileloc_incColumn (formatloc);
1390 (message ("Bad character set format: %s",
1391 cstring_fromChars (origcode)));
1394 expecttype = ctype_string;
1395 /*@switchbreak@*/ break;
1397 case 'p': /* pointer */
1398 expecttype = ctype_makePointer (ctype_void);
1400 /*@switchbreak@*/ break;
1402 case 'n': /* pointer to int, modified by call! */
1403 expecttype = ctype_combine (ctype_makePointer (ctype_int), modtype);
1405 uentry_setDefState (regArg, SS_ALLOCATED); /* corresponds to out */
1406 /*@switchbreak@*/ break;
1408 case 'm': /* in a syslog, it doesn't consume an argument */
1409 /* should check we're really doing syslog */
1411 /*@switchbreak@*/ break;
1415 expecttype = ctype_unknown;
1419 message ("Unrecognized format code: %s",
1420 cstring_fromChars (origcode)),
1421 fileloc_isDefined (formatloc)
1422 ? formatloc : g_currentloc);
1424 /*@switchbreak@*/ break;
1427 if (!(exprNode_matchArgType (expecttype, a)))
1429 if (ctype_isVoidPointer (expecttype)
1430 && ctype_isRealAbstract (a->typ)
1431 && (context_getFlag (FLG_ABSTVOIDP)))
1437 if (llgenformattypeerror
1438 (expecttype, exprNode_undefined,
1440 message ("Format argument %d to %q (%%%h) expects "
1443 uentry_getName (fcn),
1445 a->typ, exprNode_unparse (a)),
1448 if (fileloc_isDefined (formatloc)
1449 && context_getFlag (FLG_SHOWCOL))
1452 (cstring_makeLiteral
1453 ("Corresponding format code"),
1460 uentry_setType (regArg, expecttype);
1461 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
1463 if (ctype_equal (expecttype, ctype_string))
1465 exprNode_checkUse (a, sRef_makePointer (a->sref), a->loc);
1468 uentry_setType (regArg, ctype_unknown);
1469 uentry_fixupSref (regArg);
1473 exprNode_checkCallModifyVal (a->sref, args, f, ret);
1487 voptgenerror (FLG_TYPE,
1488 message ("Format string for %q has %d arg%p, given %d",
1489 uentry_getName (fcn), i - argno, nargs - argno),
1495 /* no checking possible for compile-time unknown format strings */
1498 fileloc_free (formatloc);
1502 checkScanfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1503 exprNodeList args, exprNode ret, int argno)
1507 int nargs = exprNodeList_size (args);
1508 uentryList params = uentry_getParams (fcn);
1512 ** These should be ensured by checkSpecialFunction
1515 llassert (uentryList_size (params) == argno + 1);
1516 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1518 a = exprNodeList_getN (args, argno - 1);
1519 formatloc = fileloc_copy (exprNode_loc (a));
1521 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1522 && exprNode_knownStringValue (a))
1524 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1525 char *code = format;
1528 nargs = exprNodeList_size (args);
1530 while ((code = strchr (code, '%')) != NULL)
1532 char *origcode = code;
1533 char key = *(++code);
1534 ctype modtype = ctype_int;
1535 char modifier = '\0';
1536 bool modified = TRUE;
1537 bool ignore = FALSE;
1539 fileloc_addColumn (formatloc, code - ocode);
1542 ** this is based on ANSI standard library description of fscanf
1543 ** (from ANSI standard X3.159-1989, 4.9.6.1)
1546 /* '*' suppresses assignment (does not need match argument) */
1553 fileloc_incColumn (formatloc);
1556 /* ignore field width */
1557 while (isdigit ((int) key) != 0)
1560 fileloc_incColumn (formatloc);
1565 modtype = ctype_sint; /* short */
1567 fileloc_incColumn (formatloc);
1569 else if (key == 'l' || key == 'L')
1571 modtype = ctype_lint; /* long */
1575 fileloc_incColumn (formatloc);
1582 /* now, key = type of conversion to apply */
1584 fileloc_incColumn (formatloc);
1598 message ("No argument corresponding to %q format "
1599 "code %d (%%%h): \"%s\"",
1600 uentry_getName (fcn),
1602 cstring_fromChars (format)),
1605 if (fileloc_isDefined (formatloc)
1606 && context_getFlag (FLG_SHOWCOL))
1609 (cstring_makeLiteral ("Corresponding format code"),
1617 a = exprNodeList_getN (args, i);
1620 if (!exprNode_isError (a))
1626 case '*': /* int argument for fieldwidth */
1627 expecttype = ctype_makePointer (ctype_int);
1628 *(--code) = '%'; /* convert it for next code */
1629 fileloc_subColumn (formatloc, 1);
1630 /*@switchbreak@*/ break;
1633 expecttype = ctype_makePointer (ctype_combine (ctype_uint, modtype));
1634 /*@switchbreak@*/ break;
1639 case 'X': /* unsigned int */
1640 expecttype = ctype_makePointer (ctype_combine (ctype_int, modtype));
1641 /*@switchbreak@*/ break;
1648 /* printf is double, scanf is float! */
1650 if (modifier == 'l')
1652 expecttype = ctype_makePointer (ctype_double);
1654 else if (modifier == 'L')
1656 expecttype = ctype_makePointer (ctype_ldouble);
1660 llassert (modifier == '\0');
1661 expecttype = ctype_makePointer (ctype_float);
1663 /*@switchbreak@*/ break;
1665 case 'c': /* int converted to char (check its a char?) */
1666 expecttype = ctype_makePointer (ctype_makeConj (ctype_char, ctype_uchar));
1667 /*@switchbreak@*/ break;
1669 case 's': /* string */
1670 expecttype = ctype_string;
1671 /*@switchbreak@*/ break;
1675 while (((key = *(++code)) != ']')
1678 fileloc_incColumn (formatloc);
1684 (message ("Bad character set format: %s",
1685 cstring_fromChars (origcode)));
1688 expecttype = ctype_string;
1689 /*@switchbreak@*/ break;
1691 case 'p': /* pointer */
1692 expecttype = ctype_unknown;
1694 /*@switchbreak@*/ break;
1696 case 'n': /* pointer to int, modified by call! */
1697 expecttype = ctype_makePointer (ctype_int);
1698 /*@switchbreak@*/ break;
1701 expecttype = ctype_unknown;
1705 message ("Unrecognized format code: %s",
1706 cstring_fromChars (origcode)),
1707 fileloc_isDefined (formatloc)
1708 ? formatloc : g_currentloc);
1710 /*@switchbreak@*/ break;
1713 if (!(exprNode_matchArgType (expecttype, a)))
1715 if (ctype_isVoidPointer (expecttype)
1716 && ctype_isRealAbstract (a->typ)
1717 && (context_getFlag (FLG_ABSTVOIDP)))
1723 if (modifier != '\0')
1725 if (llgenformattypeerror
1726 (expecttype, exprNode_undefined,
1728 message ("Format argument %d to %q (%%%h%h) expects "
1731 uentry_getName (fcn),
1734 a->typ, exprNode_unparse (a)),
1737 if (fileloc_isDefined (formatloc)
1738 && context_getFlag (FLG_SHOWCOL))
1741 (cstring_makeLiteral
1742 ("Corresponding format code"),
1750 if (llgenformattypeerror
1751 (expecttype, exprNode_undefined,
1753 message ("Format argument %d to %q (%%%h) expects "
1756 uentry_getName (fcn),
1758 a->typ, exprNode_unparse (a)),
1761 if (fileloc_isDefined (formatloc)
1762 && context_getFlag (FLG_SHOWCOL))
1765 (cstring_makeLiteral
1766 ("Corresponding format code"),
1774 uentry_setType (outArg, expecttype);
1775 checkOneArg (outArg, a, f, FALSE, i+1, nargs);
1776 uentry_setType (outArg, ctype_unknown);
1777 uentry_fixupSref (outArg);
1781 exprNode_checkCallModifyVal (a->sref, args, f, ret);
1786 /* a->sref = defref; */
1796 voptgenerror (FLG_TYPE,
1797 message ("Format string for %q has %d arg%p, given %d",
1798 uentry_getName (fcn), i - argno, nargs - argno),
1804 /* no checking possible for compile-time unknown format strings */
1807 fileloc_free (formatloc);
1811 checkMessageArgs (/*@notnull@*/ /*@dependent@*/ exprNode f,
1814 /*@unused@*/ int argno)
1817 ** the last argument before the elips is the format string
1820 int nargs = exprNodeList_size (args);
1825 a = exprNodeList_getN (args, argno - 1);
1826 formatloc = fileloc_copy (exprNode_loc (a));
1828 if (ctype_isUnknown (cstringType)) {
1829 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
1831 cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
1835 if (ctype_isUnknown (ctypeType)) {
1836 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
1838 ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
1842 if (ctype_isUnknown (filelocType)) {
1843 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
1845 filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
1849 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1850 && exprNode_knownStringValue (a))
1852 cstring format = multiVal_forceString (exprNode_getValue (a));
1853 char *code = cstring_toCharsSafe (format);
1856 nargs = exprNodeList_size (args);
1858 while ((code = strchr (code, '%')) != NULL)
1860 char *origcode = code;
1861 char key = *(++code);
1862 bool isOnly = FALSE;
1864 fileloc_addColumn (formatloc, code - ocode);
1866 while (key >= '0' && key <= '9')
1869 fileloc_incColumn (formatloc);
1873 fileloc_incColumn (formatloc);
1886 message ("Message missing format arg %d (%%%h): \"%s\"",
1887 i + 1, key, format),
1893 a = exprNodeList_getN (args, i);
1897 if (!exprNode_isError (a))
1901 /*@-loopswitchbreak@*/
1907 expecttype = ctype_char; break;
1909 expecttype = cstringType; break;
1911 expecttype = cstringType; isOnly = TRUE; break;
1913 expecttype = cstringType; isOnly = TRUE; break;
1914 case 'd': expecttype = ctype_int; break;
1915 case 'u': expecttype = ctype_uint; break;
1916 case 'w': expecttype = ctype_ulint; break;
1917 case 'f': expecttype = ctype_float; break;
1918 case 'b': expecttype = ctype_bool; break;
1919 case 't': expecttype = ctypeType; break;
1920 case 'l': expecttype = filelocType; break;
1921 case 'p': /* a wee bit of a hack methinks */
1922 expecttype = ctype_int;
1924 case 'r': expecttype = ctype_bool; break;
1926 expecttype = ctype_unknown;
1929 message ("Unrecognized format code: %s",
1930 cstring_fromChars (origcode)),
1931 fileloc_isDefined (formatloc)
1932 ? formatloc : g_currentloc);
1935 /*@=loopswitchbreak@*/
1937 if (!(exprNode_matchArgType (expecttype, a)))
1939 if (ctype_isVoidPointer (expecttype)
1940 && ctype_isRealAbstract (a->typ)
1941 && (context_getFlag (FLG_ABSTVOIDP)))
1947 if (llgenformattypeerror
1948 (expecttype, exprNode_undefined,
1950 message ("Format argument %d to %q (%%%h) expects "
1953 uentry_getName (fcn),
1955 a->typ, exprNode_unparse (a)),
1958 if (fileloc_isDefined (formatloc)
1959 && context_getFlag (FLG_SHOWCOL))
1962 (cstring_makeLiteral
1963 ("Corresponding format code"),
1970 if (ctype_equal (expecttype, cstringType))
1974 checkOneArg (csOnlyArg, a, f, FALSE, i+1, nargs);
1975 uentry_fixupSref (csOnlyArg);
1979 checkOneArg (csArg, a, f, FALSE, i+1, nargs);
1980 uentry_fixupSref (csArg);
1985 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
1986 uentry_fixupSref (regArg);
1995 voptgenerror (FLG_TYPE,
1996 message ("Format string for %q has %d arg%p, given %d",
1997 uentry_getName (fcn), i - argno, nargs -argno),
2003 /* no checking possible for compile-time unknown format strings */
2006 fileloc_free (formatloc);
2010 checkExpressionDefinedAux (/*@notnull@*/ exprNode e1,
2011 /*@notnull@*/ exprNode e2,
2017 bool hadUncon = FALSE;
2019 if (sRef_isGlobal (sRef_getRootBase (e1->sref)) &&
2020 sRefSet_hasUnconstrained (sets2))
2023 (FLG_EVALORDERUNCON,
2025 ("Expression may have undefined behavior (%q used in right operand "
2026 "may set global variable %q used in left operand): %s %s %s",
2027 sRefSet_unparseUnconstrained (sets2),
2028 sRef_unparse (sRef_getRootBase (e1->sref)),
2029 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2033 if (sRef_isGlobal (sRef_getRootBase (e2->sref)) &&
2034 sRefSet_hasUnconstrained (sets1))
2037 (FLG_EVALORDERUNCON,
2039 ("Expression has undefined behavior (%q used in left operand "
2040 "may set global variable %q used in right operand): %s %s %s",
2041 sRefSet_unparseUnconstrained (sets1),
2042 sRef_unparse (e2->sref),
2043 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2047 sRefSet_realElements (e1->uses, sr)
2049 if (sRef_isMeaningful (sr) && sRefSet_member (sets2, sr))
2054 ("Expression has undefined behavior (left operand uses %q, "
2055 "modified by right operand): %s %s %s",
2057 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2060 } end_sRefSet_realElements;
2062 sRefSet_realElements (sets1, sr)
2064 if (sRef_isMeaningful (sr))
2066 if (sRef_same (sr, e2->sref))
2071 ("Expression has undefined behavior (value of right operand "
2072 "modified by left operand): %s %s %s",
2073 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2076 else if (sRefSet_member (e2->uses, sr))
2081 ("Expression has undefined behavior (left operand modifies %q, "
2082 "used by right operand): %s %s %s",
2084 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2089 if (sRefSet_member (sets2, sr))
2091 if (sRef_isUnconstrained (sr))
2099 hadUncon = optgenerror
2100 (FLG_EVALORDERUNCON,
2102 ("Expression may have undefined behavior. Left operand "
2103 "calls %q; right operand calls %q. The unconstrained "
2104 "functions may modify global state used by "
2105 "the other operand): %s %s %s",
2106 sRefSet_unparseUnconstrained (sets1),
2107 sRefSet_unparseUnconstrained (sets2),
2108 exprNode_unparse (e1), lltok_unparse (op),
2109 exprNode_unparse (e2)),
2118 ("Expression has undefined behavior (both "
2119 "operands modify %q): %s %s %s",
2121 exprNode_unparse (e1),
2122 lltok_unparse (op), exprNode_unparse (e2)),
2128 } end_sRefSet_realElements;
2131 static void checkExpressionDefined (exprNode e1, exprNode e2, lltok op)
2133 bool hasError = FALSE;
2135 if (exprNode_isError (e1) || exprNode_isError (e2))
2140 if (sRefSet_member (e2->sets, e1->sref))
2142 if (e2->kind == XPR_CALL)
2148 hasError = optgenerror
2150 message ("Expression has undefined behavior "
2151 "(value of left operand is modified "
2152 "by right operand): %s %s %s",
2153 exprNode_unparse (e1), lltok_unparse (op),
2154 exprNode_unparse (e2)),
2159 if (context_getFlag (FLG_EVALORDERUNCON))
2161 if (sRefSet_member (e2->msets, e1->sref))
2163 if (e2->kind == XPR_CALL)
2169 hasError = optgenerror
2172 ("Expression has undefined behavior (value of left "
2173 "operand may be modified by right operand): %s %s %s",
2174 exprNode_unparse (e1), lltok_unparse (op),
2175 exprNode_unparse (e2)),
2183 checkExpressionDefinedAux (e1, e2, e1->sets, e2->sets, op, FLG_EVALORDER);
2185 if (context_maybeSet (FLG_EVALORDERUNCON))
2187 checkExpressionDefinedAux (e1, e2, e1->msets,
2188 e2->msets, op, FLG_EVALORDERUNCON);
2193 static void checkSequencing (exprNode p_f, exprNodeList p_args);
2196 checkArgsReal (uentry fcn, /*@dependent@*/ exprNode f, uentryList cl,
2197 exprNodeList args, bool isIter, exprNode ret)
2201 if (!exprNode_isError (f))
2203 if (!uentryList_isMissingParams (cl))
2205 int nargs = exprNodeList_size (args);
2206 int expectargs = uentryList_size (cl);
2210 if (expectargs == 0)
2218 message ("Iter %q invoked with %d args, "
2220 uentry_getName (fcn),
2228 message ("Function %s called with %d args, "
2230 exprNode_unparse (f), nargs),
2237 last = uentry_getType (uentryList_getN (cl, expectargs - 1));
2239 exprNodeList_reset (args);
2241 uentryList_elements (cl, current)
2243 ctype ct = uentry_getType (current);
2246 if (ctype_isElips (ct))
2249 ** do special checking for printf/scanf library functions
2251 ** this is kludgey code, just for handling the special case
2255 if (uentry_isPrintfLike (fcn))
2257 checkPrintfArgs (f, fcn, args, ret, i);
2260 else if (uentry_isScanfLike (fcn))
2262 checkScanfArgs (f, fcn, args, ret, i);
2265 else if (uentry_isMessageLike (fcn))
2267 checkMessageArgs (f, fcn, args, i);
2272 llassert (!uentry_isSpecialFunction (fcn));
2275 nargs = expectargs; /* avoid errors */
2280 if (i >= nargs) break;
2282 a = exprNodeList_current (args);
2283 exprNodeList_advance (args);
2287 if (exprNode_isError (a))
2294 probably necessary? I'm not sure about this one
2295 checkMacroParen (a);
2298 f->guards = guardSet_union (f->guards, a->guards);
2300 if (!(exprNode_matchArgType (ct, a)))
2302 if (ctype_isVoidPointer (ct)
2303 && (ctype_isPointer (a->typ)
2304 && (ctype_isRealAbstract (ctype_baseArrayPtr (a->typ)))))
2309 ("Pointer to abstract type (%t) used "
2311 "(arg %d to %q): %s",
2313 uentry_getName (fcn),
2314 exprNode_unparse (a)),
2322 (ct, exprNode_undefined,
2325 ("Iter %q expects arg %d to "
2326 "be %t gets %t: %s",
2327 uentry_getName (fcn),
2328 i, ct, a->typ, exprNode_unparse (a)),
2339 ("Function %q expects arg %d to be %t gets %t: %s",
2340 uentry_getName (fcn),
2341 i, ct, a->typ, exprNode_unparse (a)),
2344 DPRINTF (("Types: %s / %s",
2346 ctype_unparse (a->typ)));
2350 ** Clear null marker for abstract types.
2351 ** (It is not revealed, so suppress future messages.)
2354 if (ctype_isAbstract (a->typ))
2356 sRef_setNullUnknown (exprNode_getSref (a), a->loc);
2363 } end_uentryList_elements ;
2366 if (expectargs != nargs) /* note: not != since we may have ... */
2368 if (ctype_isElips (last))
2372 message ("Function %s called with %d args, expects at least %d",
2373 exprNode_unparse (f),
2374 nargs, expectargs - 1),
2383 message ("Iter %q invoked with %d args, expects %d",
2384 uentry_getName (fcn), nargs, expectargs),
2391 message ("Function %s called with %d args, expects %d",
2392 exprNode_unparse (f),
2405 ** Check for undefined code sequences in function arguments:
2407 ** one parameter sets something used by another parameter
2408 ** one parameter sets something set by another parameter
2412 checkSequencingOne (exprNode f, exprNodeList args,
2413 /*@notnull@*/ exprNode el, int argno)
2416 ** Do second loop, iff +undefunspec
2420 int numloops = context_maybeSet (FLG_EVALORDERUNCON) ? 2 : 1;
2422 for (checkloop = 0; checkloop < numloops; checkloop++)
2428 thissets = el->sets;
2432 llassert (checkloop == 1);
2433 thissets = el->msets;
2436 sRefSet_realElements (thissets, thisset)
2440 /*@access exprNodeList@*/
2441 for (j = 0; j < args->nelements; j++)
2443 exprNode jl = args->elements[j];
2444 int thisargno = j + 1;
2446 if (thisargno != argno && exprNode_isDefined (jl))
2448 sRefSet otheruses = jl->uses;
2450 if (sRef_isGlobal (sRef_getRootBase (jl->sref)) &&
2451 sRefSet_hasUnconstrained (thissets))
2454 (FLG_EVALORDERUNCON,
2457 ("%q used in argument %d may set "
2458 "global variable %q used by argument %d: %s(%q)",
2459 cstring_capitalizeFree (sRefSet_unparseUnconstrained (thissets)),
2462 sRef_unparse (sRef_getRootBase (jl->sref)),
2464 exprNode_unparse (f), exprNodeList_unparse (args)),
2468 if (sRefSet_member (otheruses, thisset))
2470 if (sRef_isUnconstrained (thisset))
2473 (FLG_EVALORDERUNCON,
2475 ("Unconstrained functions used in arguments %d (%q) "
2476 "and %d (%s) may modify "
2477 "or use global state in undefined way: %s(%q)",
2479 sRefSet_unparseUnconstrainedPlain (otheruses),
2481 sRef_unconstrainedName (thisset),
2482 exprNode_unparse (f),
2483 exprNodeList_unparse (args)),
2491 ("Argument %d modifies %q, used by argument %d "
2492 "(order of evaluation of actual parameters is "
2493 "undefined): %s(%q)",
2494 argno, sRef_unparse (thisset), thisargno,
2495 exprNode_unparse (f), exprNodeList_unparse (args)),
2501 sRefSet othersets = jl->sets;
2503 if (sRefSet_member (othersets, thisset))
2505 if (sRef_isUnconstrained (thisset))
2508 (FLG_EVALORDERUNCON,
2510 ("Unconstrained functions used in "
2511 "arguments %d (%q) and %d (%s) may modify "
2512 "or use global state in undefined way: %s(%q)",
2514 sRefSet_unparseUnconstrainedPlain (othersets),
2516 sRef_unconstrainedName (thisset),
2517 exprNode_unparse (f), exprNodeList_unparse (args)),
2525 ("Argument %d modifies %q, set by argument %d (order of"
2526 " evaluation of actual parameters is undefined): %s(%q)",
2527 argno, sRef_unparse (thisset), thisargno,
2528 exprNode_unparse (f), exprNodeList_unparse (args)),
2535 /*@noaccess exprNodeList@*/
2536 } end_sRefSet_realElements;
2541 checkSequencing (exprNode f, exprNodeList args)
2543 if (exprNodeList_size (args) > 1)
2548 /*@access exprNodeList*/
2550 for (i = 0; i < args->nelements; i++)
2552 el = args->elements[i];
2554 if (!exprNode_isError (el))
2556 checkSequencingOne (f, args, el, i + 1);
2559 /*@noaccess exprNodeList*/
2564 ** requires le = exprNode_getUentry (f)
2568 checkGlobMods (/*@notnull@*/ /*@dependent@*/ exprNode f,
2569 uentry le, exprNodeList args,
2570 /*@notnull@*/ exprNode ret, int specialArgs)
2572 bool isSpec = FALSE;
2573 bool hasMods = FALSE;
2575 globSet usesGlobs = globSet_undefined;
2576 sRefSet mods = sRefSet_undefined;
2577 bool freshMods = FALSE;
2578 uentryList params = uentryList_undefined;
2581 ** check globals and modifies
2586 if (!uentry_isValid (le))
2588 ctype fr = ctype_realType (f->typ);
2590 if (ctype_isFunction (fr))
2592 params = ctype_argsFunction (fr);
2596 params = uentryList_missingParams;
2599 if (!context_getFlag (FLG_MODNOMODS)
2600 && !context_getFlag (FLG_GLOBUNSPEC))
2602 checkUnspecCall (f, params, args);
2608 fname = uentry_rawName (le);
2612 if (uentry_isFunction (le))
2614 params = uentry_getParams (le);
2615 mods = uentry_getMods (le);
2616 hasMods = uentry_hasMods (le);
2617 usesGlobs = uentry_getGlobs (le);
2618 isSpec = uentry_isSpecified (le);
2620 else /* not a function */
2622 ctype ct = ctype_realType (uentry_getType (le));
2624 llassertprint (uentry_isVar (le) && ctype_isFunction (ct),
2625 ("checkModGlobs: uentry not a function: %s",
2626 uentry_unparse (le)));
2628 params = ctype_argsFunction (ct);
2638 globSet_allElements (usesGlobs, el)
2640 if (sRef_isValid (el))
2642 if (sRef_isInternalState (el) || sRef_isSystemState (el))
2644 context_usedGlobal (el);
2645 exprNode_checkUse (f, el, f->loc);
2647 if (context_checkInternalUse ())
2649 if (!context_globAccess (el))
2651 if (sRef_isSystemState (el)
2652 && !context_getFlag (FLG_MODFILESYSTEM))
2661 ("Called procedure %s may access %q, but "
2662 "globals list does not include globals %s",
2663 exprNode_unparse (f),
2665 cstring_makeLiteralTemp (sRef_isInternalState (el)
2673 else if (sRef_isNothing (el) || sRef_isSpecState (el))
2679 uentry gle = sRef_getUentry (el);
2680 sRef sr = sRef_updateSref (el);
2682 if (sRef_isUndefGlob (el))
2684 sRef_setDefined (sr, f->loc);
2685 exprNode_checkSet (f, sr);
2693 if (sRef_isAllocated (el))
2695 exprNode_checkSet (f, sr);
2699 if (sRef_isStateUndefined (sr))
2704 ("%s %q used by function undefined before call: %s",
2705 sRef_getScopeName (sr),
2707 exprNode_unparse (f)),
2709 sRef_setDefined (sr, f->loc);
2711 exprNode_checkUse (f, sr, f->loc);
2714 checkGlobUse (gle, TRUE, f);
2717 if (sRef_isKilledGlob (el))
2719 sRef_kill (sr, f->loc);
2720 context_usedGlobal (sr);
2724 } end_globSet_allElements;
2730 if (context_hasMods () || context_getFlag (FLG_MODNOMODS))
2732 sRefSet smods = sRefSet_undefined;
2735 ** NEED to check for modifies anything
2739 ** check each sRef that called function modifies (ml), is
2745 sRefSet_allElements (mods, s) /* s is something which may be modified */
2747 if (sRef_isKindSpecial (s))
2749 if (sRef_isSpecInternalState (s))
2751 if (context_getFlag (FLG_MODINTERNALSTRICT))
2753 exprNode_checkCallModifyVal (s, args, f, ret);
2757 sRefSet mmods = context_modList ();
2759 sRefSet_allElements (mmods, el)
2761 if (sRef_isInternalState (el))
2763 sRef_setModified (el);
2765 } end_sRefSet_allElements ;
2770 exprNode_checkCallModifyVal (s, args, f, ret);
2775 sRef rb = sRef_getRootBase (s);
2777 if (sRef_isGlobal (rb))
2779 context_usedGlobal (rb);
2782 if (sRef_isFileStatic (s)
2783 && !fileId_equal (fileloc_fileId (f->loc),
2784 fileloc_fileId (uentry_whereDefined (le))))
2786 smods = sRefSet_insert (smods, s);
2790 exprNode_checkCallModifyVal (s, args, f, ret);
2793 } end_sRefSet_allElements;
2798 ** Static elements in modifies set can have nasty consequences.
2799 ** (I think...have not been able to reproduce a possible bug.)
2802 if (!sRefSet_isDefined (smods))
2804 mods = sRefSet_newCopy (mods);
2807 sRefSet_allElements (smods, el)
2809 bool res = sRefSet_delete (mods, el);
2812 } end_sRefSet_allElements;
2814 sRefSet_free (smods);
2819 else if (sRefSet_isDefined (mods))
2820 { /* just check observers */
2823 sRefSet_allElements (mods, s) /* s is something which may be modified */
2825 sRef rb = sRef_getRootBase (s);
2829 if (sRef_isParam (rb))
2831 sRef b = sRef_fixBaseParam (s, args);
2833 if (sRef_isObserver (b))
2835 exprNode e = exprNodeList_nth (args, sRef_getParam (rb));
2839 message ("Function call may modify observer%q: %s",
2840 sRef_unparsePreOpt (b), exprNode_unparse (e)),
2843 sRef_showExpInfo (b);
2847 } end_sRefSet_allElements;
2851 if (!hasMods) /* no specified modifications */
2853 if (context_getFlag (FLG_MODOBSERVERUNCON))
2855 exprNodeList_elements (args, e)
2857 if (exprNode_isDefined (e))
2859 sRef s = exprNode_getSref (e);
2861 if (sRef_isObserver (s)
2862 && ctype_isMutable (sRef_getType (s)))
2865 (FLG_MODOBSERVERUNCON,
2867 ("Call to unconstrained function %s may modify observer%q: %s",
2868 exprNode_unparse (f),
2869 sRef_unparsePreOpt (s), exprNode_unparse (e)),
2872 sRef_showExpInfo (s);
2876 } end_exprNodeList_elements;
2881 checkAnyCall (f, fname, params, args, hasMods, mods, isSpec, specialArgs);
2883 ret->uses = sRefSet_union (ret->uses, f->uses);
2884 ret->sets = sRefSet_union (ret->sets, f->sets);
2885 ret->msets = sRefSet_union (ret->msets, f->msets);
2890 ** Spurious errors reported, because lclint can't tell
2891 ** mods must be fresh if freshMods is true.
2894 /*@i@*/ sRefSet_free (mods);
2900 void checkGlobUse (uentry glob, bool isCall, /*@notnull@*/ exprNode e)
2902 if (uentry_isVar (glob))
2904 if (context_inFunctionLike ())
2906 sRef sr = uentry_getSref (glob);
2908 context_usedGlobal (sr);
2910 if (context_checkGlobUse (glob))
2912 if (!context_globAccess (sr))
2918 message ("Called procedure %s may access %s %q",
2919 exprNode_unparse (e),
2920 sRef_unparseScope (sr),
2921 uentry_getName (glob)),
2928 message ("Undocumented use of %s %s",
2929 sRef_unparseScope (sr),
2930 exprNode_unparse (e)),
2939 llbug (message ("Global not variable: %q", uentry_unparse (glob)));
2943 static /*@only@*/ exprNode
2944 functionCallSafe (/*@only@*/ /*@notnull@*/ exprNode f,
2945 ctype t, /*@keep@*/ exprNodeList args)
2947 /* requires f is a non-error exprNode, with type function */
2948 cstring fname = exprNode_unparse (f);
2949 uentry le = exprNode_getUentry (f);
2950 exprNode ret = exprNode_createPartialCopy (f);
2955 ret->typ = ctype_returnValue (t);
2956 ret->kind = XPR_CALL;
2958 ret->edata = exprData_makeCall (f, args);
2961 ** Order of these steps is very important!
2963 ** Must check for argument dependencies before messing up uses and sets.
2966 if (context_getFlag (FLG_EVALORDER))
2968 exprNodeList_elements (args, current)
2970 if (exprNode_isDefined (current))
2972 exprNode_addUse (current, current->sref);
2974 } end_exprNodeList_elements;
2976 if (context_maybeSet (FLG_EVALORDER) || context_maybeSet (FLG_EVALORDERUNCON))
2978 checkSequencing (f, args);
2981 exprNodeList_elements (args, current)
2983 if (exprNode_isDefined (current) && sRef_isMeaningful (current->sref))
2985 exprNode_addUse (ret, sRef_makeDerived (current->sref));
2987 } end_exprNodeList_elements ;
2990 special = checkArgs (le, f, t, args, ret);
2991 checkGlobMods (f, le, args, ret, special);
2995 if (uentry_isValid (le)
2996 && (uentry_isFunction (le)
2997 || (uentry_isVariable (le)
2998 && ctype_isFunction (uentry_getType (le)))))
3000 exitkind exk = uentry_getExitCode (le);
3002 /* f->typ is already set to the return type */
3004 ret->sref = uentry_returnedRef (le, args);
3006 if (uentry_isFunction (le) && exprNodeList_size (args) >= 1)
3008 qual nullPred = uentry_nullPred (le);
3010 if (qual_isTrueNull (nullPred))
3012 exprNode arg = exprNodeList_head (args);
3014 if (exprNode_isDefined (arg))
3016 ret->guards = guardSet_addFalseGuard (ret->guards, arg->sref);
3019 else if (qual_isFalseNull (nullPred))
3021 exprNode arg = exprNodeList_head (args);
3023 if (exprNode_isDefined (arg))
3025 ret->guards = guardSet_addTrueGuard (ret->guards, arg->sref);
3030 llassert (qual_isUnknown (nullPred));
3034 if (exitkind_isConditionalExit (exk))
3038 ** if (arg0) then { exit! } else { ; }
3040 ** if (arg0) then { ; } else { exit! }
3045 llassert (!exprNodeList_isEmpty (args));
3046 firstArg = exprNodeList_head (args);
3048 if (exprNode_isDefined (firstArg)
3049 && !guardSet_isEmpty (firstArg->guards))
3051 usymtab_trueBranch (guardSet_undefined);
3052 usymtab_altBranch (guardSet_undefined);
3054 if (exitkind_isTrueExit (exk))
3056 usymtab_popBranches (firstArg,
3057 exprNode_makeMustExit (),
3059 TRUE, TRUEEXITCLAUSE);
3063 usymtab_popBranches (firstArg,
3065 exprNode_makeMustExit (),
3066 TRUE, FALSEEXITCLAUSE);
3070 ret->exitCode = XK_MAYEXIT;
3072 else if (exitkind_mustExit (exk))
3074 ret->exitCode = XK_MUSTEXIT;
3076 else if (exitkind_couldExit (exk))
3078 ret->exitCode = XK_MAYEXIT;
3085 if (cstring_equalLit (fname, "exit"))
3087 if (exprNodeList_size (args) == 1)
3089 exprNode arg = exprNodeList_head (args);
3091 if (exprNode_isDefined (arg) && exprNode_knownIntValue (arg))
3093 long int val = multiVal_forceInt (exprNode_getValue (arg));
3100 ("Argument to exit has implementation defined behavior: %s",
3101 exprNode_unparse (arg)),
3102 exprNode_loc (arg));
3111 exprNode_checkSetAny (ret, uentry_rawName (le));
3118 ** this is yucky! should keep the uentry as part of exprNode!
3121 /*@observer@*/ uentry
3122 exprNode_getUentry (exprNode e)
3124 if (exprNode_isError (e))
3126 return uentry_undefined;
3130 cstring s = exprNode_rootVarName (e);
3131 uentry ue = usymtab_lookupSafe (s);
3138 exprNode_makeInitBlock (lltok brace, /*@only@*/ exprNodeList inits)
3140 exprNode ret = exprNode_createPlain (ctype_unknown);
3142 ret->kind = XPR_INITBLOCK;
3143 ret->edata = exprData_makeCall (exprNode_undefined, inits);
3144 ret->loc = fileloc_update (ret->loc, lltok_getLoc (brace));
3150 exprNode_functionCall (/*@only@*/ exprNode f, /*@only@*/ exprNodeList args)
3156 if (exprNode_isUndefined (f))
3159 exprNodeList_free (args);
3160 return exprNode_undefined;
3163 t = exprNode_getType (f);
3165 if (sRef_isLocalVar (f->sref))
3167 exprNode_checkUse (f, f->sref, f->loc);
3169 if (sRef_possiblyNull (f->sref))
3171 if (!usymtab_isGuarded (f->sref))
3173 if (optgenerror (FLG_NULLDEREF,
3174 message ("Function call using %s pointer %q",
3175 sRef_nullMessage (f->sref),
3176 sRef_unparse (f->sref)),
3179 sRef_showNullInfo (f->sref);
3180 sRef_setNullError (f->sref);
3188 if (ctype_isRealFunction (t))
3190 exprNode ret = functionCallSafe (f, t, args);
3194 else if (ctype_isUnknown (t))
3196 exprNode ret = exprNode_createPartialCopy (f);
3202 exprNodeList_elements (args, current)
3204 if (exprNode_isDefined (current))
3206 exprNode_checkUse (ret, current->sref, ret->loc);
3209 ** also, anything derivable from current->sref may be used
3212 exprNode_addUse (ret, sRef_makeDerived (current->sref));
3213 exprNode_mergeUSs (ret, current);
3215 } end_exprNodeList_elements;
3217 ret->edata = exprData_makeCall (f, args);
3218 ret->kind = XPR_CALL;
3220 tstring = cstring_copy (exprNode_unparse (f));
3222 cstring_markOwned (tstring);
3223 exprNode_checkSetAny (ret, tstring);
3229 voptgenerror (FLG_TYPE,
3230 message ("Call to non-function (type %t): %s", t,
3231 exprNode_unparse (f)),
3234 exprNodeList_free (args);
3236 return (exprNode_makeError ());
3241 exprNode_fieldAccess (/*@only@*/ exprNode s, /*@only@*/ cstring f)
3243 exprNode ret = exprNode_createPartialCopy (s);
3245 ret->kind = XPR_FACCESS;
3247 if (exprNode_isError (s))
3249 ret->edata = exprData_makeField (s, f);
3254 ctype t = exprNode_getType (s);
3255 ctype tr = ctype_realType (t);
3257 checkMacroParen (s);
3259 ret->edata = exprData_makeField (s, f);
3261 if (ctype_isStructorUnion (tr))
3263 uentry tf = uentryList_lookupField (ctype_getFields (tr), f);
3265 if (uentry_isUndefined (tf))
3267 voptgenerror (FLG_TYPE,
3268 message ("Access non-existent field %s of %t: %s", f, t,
3269 exprNode_unparse (ret)),
3276 uentry_setUsed (tf, exprNode_loc (ret));
3278 ret->typ = uentry_getType (tf);
3279 checkSafeUse (ret, s->sref);
3281 ret->sref = sRef_makeField (s->sref, uentry_rawName (tf));
3285 else /* isStructorUnion */
3287 if (ctype_isRealAbstract (tr))
3291 message ("Access field of abstract type (%t): %s.%s",
3292 t, exprNode_unparse (s), f),
3294 ret->typ = ctype_unknown;
3298 if (ctype_isKnown (tr))
3303 ("Access field of non-struct or union (%t): %s.%s",
3304 t, exprNode_unparse (s), f),
3307 ret->typ = ctype_unknown;
3311 cstring sn = cstring_copy (f);
3313 checkSafeUse (ret, s->sref);
3314 cstring_markOwned (sn);
3315 ret->sref = sRef_makeField (s->sref, sn);
3327 exprNode_addParens (/*@only@*/ lltok lpar, /*@only@*/ exprNode e)
3329 exprNode ret = exprNode_createPartialCopy (e);
3331 ret->loc = fileloc_update (ret->loc, lltok_getLoc (lpar));
3332 ret->kind = XPR_PARENS;
3333 ret->edata = exprData_makeUop (e, lpar);
3335 if (!exprNode_isError (e))
3337 ret->exitCode = e->exitCode;
3338 ret->canBreak = e->canBreak;
3339 ret->mustBreak = e->mustBreak;
3340 ret->isJumpPoint = e->isJumpPoint;
3341 ret->sref = e->sref;
3348 exprNode_arrowAccess (/*@only@*/ exprNode s, /*@only@*/ cstring f)
3350 exprNode ret = exprNode_createPartialCopy (s);
3352 ret->edata = exprData_makeField (s, f);
3353 ret->kind = XPR_ARROW;
3355 if (exprNode_isError (s))
3361 ctype t = exprNode_getType (s);
3362 ctype tr = ctype_realType (t);
3364 checkMacroParen (s);
3366 (void) ctype_fixArrayPtr (tr); /* REWRITE THIS */
3368 if (ctype_isRealPointer (tr))
3370 ctype b = ctype_realType (ctype_baseArrayPtr (tr));
3372 if (ctype_isStructorUnion (b))
3374 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
3376 if (sRef_isKnown (s->sref) && sRef_possiblyNull (s->sref))
3378 if (!usymtab_isGuarded (s->sref) && !context_inProtectVars ())
3382 message ("Arrow access from %s pointer%q: %s",
3383 sRef_nullMessage (s->sref),
3384 sRef_unparsePreOpt (s->sref),
3385 exprNode_unparse (ret)),
3388 sRef_showNullInfo (s->sref);
3389 sRef_setNullError (s->sref);
3394 if (uentry_isUndefined (fentry))
3398 message ("Access non-existent field %s of %t: %s",
3399 f, t, exprNode_unparse (ret)),
3401 ret->typ = ctype_unknown;
3408 ** was safeUse: shouldn't be safe!
3411 ** rec must be defined,
3412 ** *rec must be allocated
3413 ** rec->field need only be defined it if is an rvalue
3416 uentry_setUsed (fentry, exprNode_loc (ret));
3417 ret->typ = uentry_getType (fentry);
3419 exprNode_checkUse (ret, s->sref, s->loc);
3421 /* exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc); */
3422 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
3426 else /* Pointer to something that is not a struct or union*/
3428 if (ctype_isRealAbstract (tr))
3430 ctype xrt = ctype_forceRealType (tr);
3434 message ("Arrow access field of abstract type (%t): %s->%s",
3435 t, exprNode_unparse (s), f),
3439 ** Set the state correctly, as if the abstraction is broken.
3442 if (ctype_isRealPointer (xrt) &&
3443 (b = ctype_realType (ctype_baseArrayPtr (xrt)),
3444 ctype_isStructorUnion (b)))
3446 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
3447 ret->typ = uentry_getType (fentry);
3448 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
3452 ret->typ = ctype_unknown;
3453 ret->sref = sRef_undefined;
3456 else /* not a struct, union or abstract */
3458 if (ctype_isUnknown (tr)) {
3459 cstring sn = cstring_copy (f);
3461 DPRINTF (("Here: %s", exprNode_unparse (s)));
3463 exprNode_checkUse (ret, s->sref, s->loc);
3464 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
3466 cstring_markOwned (sn);
3467 ret->sref = sRef_makeArrow (s->sref, sn);
3469 ret->kind = XPR_ARROW;
3474 message ("Arrow access field of non-struct or union "
3475 "pointer (%t): %s->%s",
3476 t, exprNode_unparse (s), f),
3479 ret->typ = ctype_unknown;
3480 ret->sref = sRef_undefined;
3485 else /* its not a pointer */
3487 if (!ctype_isUnknown (tr))
3491 message ("Arrow access of non-pointer (%t): %s->%s",
3492 t, exprNode_unparse (s), f),
3495 ret->typ = ctype_unknown;
3496 ret->sref = sRef_undefined;
3500 cstring sn = cstring_copy (f);
3502 DPRINTF (("Here: %s", exprNode_unparse (s)));
3504 exprNode_checkUse (ret, s->sref, s->loc);
3505 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
3507 cstring_markOwned (sn);
3508 ret->sref = sRef_makeArrow (s->sref, sn);
3510 ret->kind = XPR_ARROW;
3521 ** only postOp's in C: i++ and i--
3525 exprNode_postOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
3527 /* check modification also */
3528 /* cstring opname = lltok_unparse (op);*/
3530 exprNode ret = exprNode_createPartialCopy (e);
3532 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
3533 ret->kind = XPR_POSTOP;
3534 ret->edata = exprData_makeUop (e, op);
3536 if (!exprNode_isDefined (e))
3541 checkMacroParen (e);
3543 exprNode_checkUse (ret, e->sref, e->loc);
3544 exprNode_checkSet (ret, e->sref);
3546 t = exprNode_getType (e);
3548 if (sRef_isUnsafe (e->sref))
3550 voptgenerror (FLG_MACROPARAMS,
3551 message ("Operand of %s is macro parameter (non-functional): %s%s",
3552 lltok_unparse (op), exprNode_unparse (e), lltok_unparse (op)),
3554 sRef_makeSafe (e->sref);
3555 sRef_makeSafe (ret->sref);
3558 if (ctype_isForceRealNumeric (&t) || ctype_isRealAP (t))
3564 if (ctype_isRealAbstract (t))
3568 message ("Operand of %s is abstract type (%t): %s",
3569 lltok_unparse (op), t, exprNode_unparse (e)),
3576 message ("Operand of %s is non-numeric (%t): %s",
3577 lltok_unparse (op), t, exprNode_unparse (e)),
3580 ret->typ = ctype_unknown;
3583 /* if (ctype_isZero (t)) e->typ = ctype_int; */
3585 exprNode_checkModify (e, ret);
3591 exprNode_preOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
3593 bool checkMod = FALSE;
3595 int opid = lltok_getTok (op);
3596 exprNode ret = exprNode_createSemiCopy (e);
3598 exprNode_copySets (ret, e);
3600 multiVal_free (ret->val);
3601 ret->val = multiVal_undefined;
3602 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
3603 ret->kind = XPR_PREOP;
3604 ret->edata = exprData_makeUop (e, op);
3606 if (exprNode_isError (e))
3611 checkMacroParen (e);
3613 te = exprNode_getType (e);
3614 tr = ctype_realType (te);
3616 if (opid != TAMPERSAND)
3618 exprNode_checkUse (ret, e->sref, e->loc);
3620 if (ctype_isRealAbstract (tr)
3621 && (!(ctype_isRealBool (te) && (opid == TEXCL))))
3623 if (optgenerror (FLG_ABSTRACT,
3624 message ("Operand of %s is abstract type (%t): %s",
3625 lltok_unparse (op), tr,
3626 exprNode_unparse (ret)),
3629 tr = te = ctype_unknown;
3630 ret->typ = ctype_unknown;
3631 sRef_setNullError (e->sref);
3639 case DEC_OP: /* should also check modification! */
3641 if (sRef_isMacroParamRef (e->sref))
3645 message ("Operand of %s is macro parameter (non-functional): %s",
3646 lltok_unparse (op), exprNode_unparse (ret)),
3651 exprNode_checkSet (ret, e->sref);
3654 if (ctype_isForceRealNumeric (&tr) || ctype_isRealAP (tr))
3659 if (context_msgStrictOps ())
3663 message ("Operand of %s is non-numeric (%t): %s",
3664 lltok_unparse (op), te, exprNode_unparse (ret)),
3667 ret->typ = ctype_int;
3675 if (ctype_isForceRealNumeric (&tr))
3679 ret->val = multiVal_invert (exprNode_getValue (e));
3683 ret->val = multiVal_copy (exprNode_getValue (e));
3688 if (context_msgStrictOps ())
3692 message ("Operand of %s is non-numeric (%t): %s",
3693 lltok_unparse (op), te, exprNode_unparse (ret)),
3697 ret->typ = ctype_int;
3701 case TEXCL: /* maybe this should be restricted */
3702 guardSet_flip (ret->guards);
3704 if (ctype_isRealBool (te))
3710 if (ctype_isRealPointer (tr))
3712 if (sRef_isKnown (e->sref))
3714 ret->guards = guardSet_addFalseGuard (ret->guards, e->sref);
3718 (FLG_BOOLOPS, FLG_PTRNEGATE,
3719 message ("Operand of %s is non-boolean (%t): %s",
3720 lltok_unparse (op), te, exprNode_unparse (ret)),
3727 message ("Operand of %s is non-boolean (%t): %s",
3728 lltok_unparse (op), te, exprNode_unparse (ret)),
3732 ret->typ = ctype_bool;
3737 if (ctype_isForceRealInt (&tr))
3742 if (context_msgStrictOps ())
3746 message ("Operand of %s is non-integer (%t): %s",
3747 lltok_unparse (op), te, exprNode_unparse (ret)),
3751 if (ctype_isInt (e->typ))
3757 ret->typ = ctype_int;
3763 ret->typ = ctype_makePointer (e->typ);
3765 if (sRef_isKnown (e->sref))
3767 ret->sref = sRef_makeAddress (e->sref);
3774 if (ctype_isAP (tr))
3776 ret->typ = ctype_baseArrayPtr (e->typ);
3780 if (ctype_isKnown (te))
3782 if (ctype_isFunction (te))
3788 message ("Dereference of function type (%t): %s",
3789 te, exprNode_unparse (ret)),
3794 voptgenerror (FLG_TYPE,
3795 message ("Dereference of non-pointer (%t): %s",
3796 te, exprNode_unparse (ret)),
3798 ret->typ = ctype_unknown;
3803 ret->typ = ctype_unknown;
3808 if (sRef_isKnown (e->sref))
3810 if (sRef_possiblyNull (e->sref))
3812 if (!usymtab_isGuarded (e->sref) && !context_inProtectVars ())
3816 message ("Dereference of %s pointer %q: %s",
3817 sRef_nullMessage (e->sref),
3818 sRef_unparse (e->sref),
3819 exprNode_unparse (ret)),
3822 sRef_showNullInfo (e->sref);
3823 sRef_setNotNull (e->sref, e->loc); /* suppress future messages */
3828 ret->sref = sRef_makePointer (e->sref);
3833 llbug (message ("exprNode_preOp: unhandled op: %s", lltok_unparse (op)));
3838 exprNode_checkModify (e, ret);
3845 ** any reason to disallow sizeof (abstract type) ?
3849 ** used by both sizeof
3853 ctype sizeof_resultType (void)
3855 static ctype sizet = ctype_unknown;
3857 if (ctype_isUnknown (sizet))
3859 if (usymtab_existsType (cstring_makeLiteralTemp ("size_t")))
3861 sizet = uentry_getAbstractType (usymtab_lookup (cstring_makeLiteralTemp ("size_t")));
3865 sizet = ctype_ulint;
3872 exprNode_sizeofType (/*@only@*/ qtype qt)
3874 exprNode ret = exprNode_create (sizeof_resultType ());
3875 ctype ct = qtype_getType (qt);
3877 ret->kind = XPR_SIZEOFT;
3878 ret->edata = exprData_makeSizeofType (qt);
3880 voptgenerror (FLG_SIZEOFTYPE,
3881 message ("Parameter to sizeof is type %s: %s",
3883 exprNode_unparse (ret)),
3890 exprNode_alignofType (/*@only@*/ qtype qt)
3892 exprNode ret = exprNode_create (sizeof_resultType ());
3893 ctype ct = qtype_getType (qt);
3895 ret->kind = XPR_ALIGNOFT;
3896 ret->edata = exprData_makeSizeofType (qt);
3898 voptgenerror (FLG_SIZEOFTYPE,
3899 message ("Parameter to alignof is type %s: %s",
3901 exprNode_unparse (ret)),
3907 exprNode exprNode_offsetof (qtype qt, cstringList s)
3909 exprNode ret = exprNode_create (sizeof_resultType ());
3910 ctype ct = qtype_getType (qt);
3912 ret->kind = XPR_OFFSETOF;
3913 ret->edata = exprData_makeOffsetof (qt, s);
3915 if (!ctype_isRealSU (ct))
3917 voptgenerror (FLG_TYPE,
3918 message ("First parameter to offsetof is not a "
3919 "struct or union type (type %s): %s",
3921 exprNode_unparse (ret)),
3928 cstringList_elements (s, el) {
3932 if (ctype_isUndefined (lt))
3936 else if (!ctype_isRealSU (lt))
3938 voptgenerror (FLG_TYPE,
3939 message ("Inner offsetof type is not a "
3940 "struct or union type (type %s before field %s): %s",
3941 ctype_unparse (lt), el,
3942 exprNode_unparse (ret)),
3948 fields = ctype_getFields (ctype_realType (lt));
3949 fld = uentryList_lookupField (fields, el);
3950 DPRINTF (("Try: %s / %s", ctype_unparse (lt), el));
3952 if (uentry_isUndefined (fld))
3954 if (ctype_equal (lt, ct)) {
3955 voptgenerror (FLG_TYPE,
3956 message ("Field %s in offsetof is not the "
3957 "name of a field of %s: %s",
3960 exprNode_unparse (ret)),
3963 voptgenerror (FLG_TYPE,
3964 message ("Deep field %s in offsetof is not the "
3965 "name of a field of %s: %s",
3968 exprNode_unparse (ret)),
3974 lt = uentry_getType (fld);
3977 } end_cstringList_elements;
3979 /* Should report error if its a bit field - behavior is undefined! */
3986 exprNode_sizeofExpr (/*@only@*/ exprNode e)
3990 if (exprNode_isUndefined (e))
3992 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
3993 ret->edata = exprData_makeSingle (e);
3994 ret->typ = sizeof_resultType ();
3995 ret->kind = XPR_SIZEOF;
3999 uentry u = exprNode_getUentry (e);
4001 ret = exprNode_createPartialCopy (e);
4002 ret->edata = exprData_makeSingle (e);
4004 ret->typ = sizeof_resultType ();
4005 ret->kind = XPR_SIZEOF;
4007 if (uentry_isValid (u)
4008 && uentry_isRefParam (u)
4009 && ctype_isRealArray (uentry_getType (u)))
4012 (FLG_SIZEOFFORMALARRAY,
4013 message ("Parameter to sizeof is an array-type function parameter: %s",
4014 exprNode_unparse (ret)),
4020 ** sizeof (x) doesn't "really" use x
4027 exprNode_alignofExpr (/*@only@*/ exprNode e)
4031 if (exprNode_isUndefined (e))
4033 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4037 ret = exprNode_createPartialCopy (e);
4040 ret->edata = exprData_makeSingle (e);
4041 ret->typ = sizeof_resultType ();
4042 ret->kind = XPR_ALIGNOF;
4045 ** sizeof (x) doesn't "really" use x
4052 exprNode_cast (/*@only@*/ lltok tok, /*@only@*/ exprNode e, /*@only@*/ qtype q)
4058 if (exprNode_isError (e))
4061 lltok_release (tok);
4062 return exprNode_undefined;
4065 checkMacroParen (e);
4067 c = qtype_getType (q);
4068 t = exprNode_getType (e);
4070 ret = exprNode_createPartialCopy (e);
4072 ret->loc = fileloc_update (ret->loc, lltok_getLoc (tok));
4074 ret->kind = XPR_CAST;
4075 ret->edata = exprData_makeCast (tok, e, q);
4077 if (ctype_isRealSU (ctype_getBaseType (sRef_getType (e->sref))))
4080 ** This is a bit of a hack to avoid a problem
4081 ** when the code does,
4082 ** (some other struct) x
4087 ret->sref = sRef_copy (e->sref);
4088 usymtab_addForceMustAlias (ret->sref, e->sref);
4089 sRef_setTypeFull (ret->sref, c);
4090 DPRINTF (("Cast: %s -> %s", sRef_unparseFull (e->sref),
4091 sRef_unparseFull (ret->sref)));
4095 ret->sref = e->sref;
4096 sRef_setTypeFull (ret->sref, c);
4097 DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref)));
4104 ** void * <-> abstract * (if FLG_ABSTVOIDP)
4105 ** abstract * <-> void * (if FLG_ABSTVOIDP)
4108 if (ctype_isVoid (c)) /* cast to void is always okay --- discard value */
4112 else if (ctype_isRealAP (c)) /* casting to array or pointer */
4114 ctype bc = ctype_getBaseType (c);
4115 ctype bt = ctype_getBaseType (t);
4116 ctype rt = ctype_realType (t);
4118 if (ctype_isFunction (ctype_baseArrayPtr (ctype_realType (c)))
4119 && (ctype_isArrayPtr (rt)
4120 && !ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
4124 message ("Cast from function pointer type (%t) to "
4125 "non-function pointer (%t): %s",
4126 c, t, exprNode_unparse (ret)),
4130 if (!ctype_isFunction (ctype_baseArrayPtr (c))
4131 && (ctype_isArrayPtr (rt)
4132 && ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
4136 message ("Cast from non-function pointer type (%t) to "
4137 "function pointer (%t): %s",
4138 c, t, exprNode_unparse (ret)),
4142 if (exprNode_isZero (e) && context_getFlag (FLG_ZEROPTR) &&
4143 !(ctype_isRealAbstract (bc)
4144 && context_hasAccess (ctype_typeId (bc))))
4146 ; /* okay to cast zero */
4150 if (ctype_isRealAbstract (bc)
4151 && !context_hasAccess (ctype_typeId (bc)))
4153 if (ctype_isVoidPointer (t) || ctype_isUnknown (t))
4157 message ("Cast to underlying abstract type %t: %s",
4158 c, exprNode_unparse (ret)),
4165 message ("Cast to underlying abstract type %t: %s",
4166 c, exprNode_unparse (ret)),
4171 if (ctype_isRealAbstract (bt)
4172 && !context_hasAccess (ctype_typeId (bt)))
4174 if (ctype_isUnknown (c) || ctype_isVoidPointer (c))
4178 message ("Cast from underlying abstract type %t: %s",
4179 t, exprNode_unparse (ret)),
4186 message ("Cast from underlying abstract type %t: %s",
4187 t, exprNode_unparse (ret)),
4195 ctype bt = ctype_realType (ctype_getBaseType (t));
4196 ctype bc = ctype_realType (ctype_getBaseType (c));
4198 if (ctype_isAbstract (bt) && !context_hasAccess (ctype_typeId (bt)))
4200 if (ctype_match (c, t))
4202 if (ctype_equal (c, t))
4206 message ("Redundant cast involving abstract type %t: %s",
4207 bt, exprNode_unparse (ret)),
4215 message ("Cast from abstract type %t: %s",
4216 bt, exprNode_unparse (ret)),
4221 if (ctype_isAbstract (bc)
4222 && !context_hasAccess (ctype_typeId (bc)))
4224 if (ctype_match (c, t))
4232 message ("Cast to abstract type %t: %s", bc,
4233 exprNode_unparse (ret)),
4239 if (ctype_isAbstract (c))
4241 if (sRef_isExposed (e->sref) || sRef_isOnly (e->sref))
4243 /* okay, cast exposed to abstract */
4244 sRef_clearExKindComplete (ret->sref, fileloc_undefined);
4248 if (ctype_isVisiblySharable (t)
4249 && sRef_isExternallyVisible (e->sref)
4250 && !(ctype_isAbstract (t)
4251 && context_hasAccess (ctype_typeId (t))))
4255 message ("Cast to abstract type from externally visible "
4256 "mutable storage exposes rep of %s: %s",
4258 exprNode_unparse (e)),
4268 evaluationOrderUndefined (lltok op)
4270 int opid = lltok_getTok (op);
4272 return (opid != AND_OP && opid != OR_OP);
4275 static bool checkIntegral (/*@notnull@*/ exprNode e1,
4276 /*@notnull@*/ exprNode e2,
4277 /*@notnull@*/ exprNode ret,
4282 ctype te1 = exprNode_getType (e1);
4283 ctype te2 = exprNode_getType (e2);
4285 ctype tr1 = ctype_realishType (te1);
4286 ctype tr2 = ctype_realishType (te2);
4288 if (ctype_isForceRealInt (&tr1) && ctype_isForceRealInt (&tr2))
4294 if (context_msgStrictOps ())
4296 if (!ctype_isInt (tr1) && !ctype_isInt (tr2))
4298 if (ctype_sameName (te1, te2))
4302 message ("Operands of %s are non-integer (%t): %s",
4303 lltok_unparse (op), te1,
4304 exprNode_unparse (ret)),
4311 message ("Operands of %s are non-integers (%t, %t): %s",
4312 lltok_unparse (op), te1, te2,
4313 exprNode_unparse (ret)),
4317 else if (!ctype_isInt (tr1))
4321 message ("Left operand of %s is non-integer (%t): %s",
4322 lltok_unparse (op), te1, exprNode_unparse (ret)),
4326 /* !ctype_isInt (te2) */
4330 message ("Right operand of %s is non-integer (%t): %s",
4331 lltok_unparse (op), te2, exprNode_unparse (ret)),
4341 ** returns exprNode representing e1 op e2
4343 ** uses msg if there are errors
4344 ** can be used for both assignment ops and regular ops
4349 static /*@only@*/ /*@notnull@*/ exprNode
4350 exprNode_makeOp (/*@keep@*/ exprNode e1, /*@keep@*/ exprNode e2,
4351 /*@keep@*/ lltok op)
4353 ctype te1, te2, tr1, tr2, tret;
4354 int opid = lltok_getTok (op);
4355 bool hasError = FALSE;
4358 if (exprNode_isError (e1))
4360 ret = exprNode_createPartialNVCopy (e2);
4364 ret = exprNode_createPartialNVCopy (e1);
4367 ret->val = multiVal_undefined;
4369 ret->edata = exprData_makeOp (e1, e2, op);
4371 if (exprNode_isError (e1) || exprNode_isError (e2))
4373 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
4374 || opid == EQ_OP || opid == NE_OP
4375 || opid == AND_OP || opid == OR_OP)
4377 ret->typ = ctype_bool;
4380 if (exprNode_isDefined (e1))
4382 exprNode_checkUse (ret, e1->sref, e1->loc);
4385 if (exprNode_isDefined (e2))
4387 exprNode_mergeUSs (ret, e2);
4388 exprNode_checkUse (ret, e2->sref, e2->loc);
4394 tret = ctype_unknown;
4395 te1 = exprNode_getType (e1);
4396 DPRINTF (("te1 = %s / %s", exprNode_unparse (e1), ctype_unparse (te1)));
4398 te2 = exprNode_getType (e2);
4400 tr1 = ctype_realishType (te1);
4401 tr2 = ctype_realishType (te2);
4405 ret->guards = guardSet_or (ret->guards, e2->guards);
4407 else if (opid == AND_OP)
4409 ret->guards = guardSet_and (ret->guards, e2->guards);
4416 if (opid == EQ_OP || opid == NE_OP)
4418 exprNode temp1 = e1, temp2 = e2;
4420 /* could do NULL == x */
4422 if (exprNode_isNullValue (e1) || exprNode_isUnknownConstant (e1))
4424 temp1 = e2; temp2 = e1;
4427 if (exprNode_isNullValue (temp2) || exprNode_isUnknownConstant (temp2))
4429 reflectNullTest (temp1, (opid == NE_OP));
4430 guardSet_free (ret->guards);
4431 ret->guards = guardSet_copy (temp1->guards);
4435 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
4436 || opid == EQ_OP || opid == NE_OP || opid == AND_OP || opid == OR_OP)
4441 if (anyAbstract (tr1, tr2) &&
4442 (!((ctype_isRealBool (te1) || ctype_isRealBool (te2)) &&
4443 (opid == AND_OP || opid == OR_OP
4444 || opid == EQ_OP || opid == NE_OP))))
4446 abstractOpError (tr1, tr2, op, e1, e2, e1->loc, e2->loc);
4448 else if (ctype_isUnknown (te1) || ctype_isUnknown (te2))
4450 /* unknown types, no comparisons possible */
4456 case TMULT: /* multiplication and division: */
4458 case MUL_ASSIGN: /* numeric, numeric -> numeric */
4459 case DIV_ASSIGN: /* */
4461 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
4464 case TPLUS: /* addition and subtraction: */
4465 case TMINUS: /* pointer, int -> pointer */
4466 case SUB_ASSIGN: /* int, pointer -> pointer */
4467 case ADD_ASSIGN: /* numeric, numeric -> numeric */
4469 tr1 = ctype_fixArrayPtr (tr1);
4471 if ((ctype_isRealPointer (tr1) && !exprNode_isNullValue (e1))
4472 && (!ctype_isRealPointer (tr2) && ctype_isRealInt (tr2)))
4476 if (context_msgPointerArith ())
4480 message ("Pointer arithmetic (%t, %t): %s",
4481 te1, te2, exprNode_unparse (ret)),
4485 if (sRef_possiblyNull (e1->sref)
4486 && !usymtab_isGuarded (e1->sref))
4489 (FLG_NULLPOINTERARITH,
4490 message ("Pointer arithmetic involving possibly "
4491 "null pointer %s: %s",
4492 exprNode_unparse (e1),
4493 exprNode_unparse (ret)),
4497 ret->sref = sRef_copy (e1->sref);
4499 sRef_setNullError (ret->sref);
4502 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
4503 ** since is points to storage that should not be deallocated
4504 ** through this pointer.
4507 if (sRef_isOnly (ret->sref)
4508 || sRef_isFresh (ret->sref))
4510 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
4515 else if ((!ctype_isRealPointer(tr1) && ctype_isRealInt (tr1))
4516 && (ctype_isRealPointer (tr2) && !exprNode_isNullValue (e2)))
4518 if (context_msgPointerArith ())
4522 message ("Pointer arithmetic (%t, %t): %s",
4523 te1, te2, exprNode_unparse (ret)),
4527 if (sRef_possiblyNull (e1->sref)
4528 && !usymtab_isGuarded (e1->sref))
4531 (FLG_NULLPOINTERARITH,
4532 message ("Pointer arithmetic involving possibly "
4533 "null pointer %s: %s",
4534 exprNode_unparse (e2),
4535 exprNode_unparse (ret)),
4539 ret->sref = sRef_copy (e2->sref);
4541 sRef_setNullError (ret->sref);
4544 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
4545 ** since is points to storage that should not be deallocated
4546 ** through this pointer.
4549 if (sRef_isOnly (ret->sref)
4550 || sRef_isFresh (ret->sref)) {
4551 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
4555 ret->sref = e2->sref;
4559 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
4564 case LEFT_ASSIGN: /* Shifts: should be unsigned values */
4568 case TAMPERSAND: /* bitwise & */
4570 case TCIRC: /* ^ (XOR) */
4575 bool reported = FALSE;
4576 flagcode code = FLG_BITWISEOPS;
4578 if (opid == LEFT_OP || opid == LEFT_ASSIGN
4579 || opid == RIGHT_OP || opid == RIGHT_ASSIGN) {
4580 code = FLG_SHIFTSIGNED;
4583 if (!ctype_isUnsigned (tr1))
4585 if (exprNode_isNonNegative (e1)) {
4588 reported = optgenerror
4590 message ("Left operand of %s is not unsigned value (%t): %s",
4591 lltok_unparse (op), te1,
4592 exprNode_unparse (ret)),
4602 /* right need not be signed for shifts */
4603 if (code != FLG_SHIFTSIGNED
4604 && !ctype_isUnsigned (tr2))
4606 if (!exprNode_isNonNegative (e2)) {
4607 reported = optgenerror
4609 message ("Right operand of %s is not unsigned value (%t): %s",
4610 lltok_unparse (op), te2,
4611 exprNode_unparse (ret)),
4619 if (!checkIntegral (e1, e2, ret, op)) {
4620 te1 = ctype_unknown;
4624 DPRINTF (("Set: %s", ctype_unparse (te1)));
4627 ** tret is the widest type of te1 and te2
4630 tret = ctype_widest (te1, te2);
4635 if (checkIntegral (e1, e2, ret, op)) {
4638 tret = ctype_unknown;
4643 case TLT: /* comparisons */
4644 case TGT: /* numeric, numeric -> bool */
4645 if ((ctype_isReal (tr1) && !ctype_isInt (tr1))
4646 || (ctype_isReal (tr2) && !ctype_isInt (tr2)))
4649 bool fepsilon = FALSE;
4651 if (!ctype_isReal (rtype) || ctype_isInt (rtype))
4656 if (opid == TLT || opid == TGT)
4658 uentry ue1 = exprNode_getUentry (e1);
4659 uentry ue2 = exprNode_getUentry (e2);
4662 ** FLT_EPSILON, etc. really is a variable, not
4666 if (uentry_isVariable (ue1))
4668 cstring uname = uentry_rawName (ue1);
4670 if (cstring_equalLit (uname, "FLT_EPSILON")
4671 || cstring_equalLit (uname, "DBL_EPSILON")
4672 || cstring_equalLit (uname, "LDBL_EPSILON"))
4678 if (uentry_isVariable (ue2))
4680 cstring uname = uentry_rawName (ue2);
4682 if (cstring_equalLit (uname, "FLT_EPSILON")
4683 || cstring_equalLit (uname, "DBL_EPSILON")
4684 || cstring_equalLit (uname, "LDBL_EPSILON"))
4693 ; /* Don't complain. */
4699 message ("Dangerous comparison involving %s types: %s",
4700 ctype_unparse (rtype),
4701 exprNode_unparse (ret)),
4710 ** Types should match.
4713 if (!exprNode_matchTypes (e1, e2))
4715 hasError = gentypeerror
4717 message ("Operands of %s have incompatible types (%t, %t): %s",
4718 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
4724 || (ctype_isForceRealNumeric (&tr1)
4725 && ctype_isForceRealNumeric (&tr2)) ||
4726 (ctype_isRealPointer (tr1) && ctype_isRealPointer (tr2)))
4732 if ((ctype_isRealNumeric (tr1) && ctype_isRealPointer (tr2)) ||
4733 (ctype_isRealPointer (tr1) && ctype_isRealNumeric (tr2)))
4737 message ("Comparison of pointer and numeric (%t, %t): %s",
4738 te1, te2, exprNode_unparse (ret)),
4743 (void) checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
4748 /* EQ_OP should NOT be used with booleans (unless one is FALSE) */
4750 if ((opid == EQ_OP || opid == NE_OP) &&
4751 ctype_isDirectBool (tr1) && ctype_isDirectBool (tr2))
4754 ** is one a variable?
4757 if (uentry_isVariable (exprNode_getUentry (e1))
4758 || uentry_isVariable (exprNode_getUentry (e2)))
4761 ** comparisons with FALSE are okay
4764 if (exprNode_isFalseConstant (e1)
4765 || exprNode_isFalseConstant (e2))
4774 ("Use of %q with %s variables (risks inconsistency because "
4775 "of multiple true values): %s",
4776 cstring_makeLiteral ((opid == EQ_OP) ? "==" : "!="),
4777 context_printBoolName (), exprNode_unparse (ret)),
4784 case AND_OP: /* bool, bool -> bool */
4787 if (ctype_isForceRealBool (&tr1) && ctype_isForceRealBool (&tr2))
4793 if (context_maybeSet (FLG_BOOLOPS))
4795 if (!ctype_isRealBool (te1) && !ctype_isRealBool (te2))
4797 if (ctype_sameName (te1, te2))
4801 message ("Operands of %s are non-boolean (%t): %s",
4802 lltok_unparse (op), te1,
4803 exprNode_unparse (ret)),
4811 ("Operands of %s are non-booleans (%t, %t): %s",
4812 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
4816 else if (!ctype_isRealBool (te1))
4820 message ("Left operand of %s is non-boolean (%t): %s",
4821 lltok_unparse (op), te1, exprNode_unparse (ret)),
4824 else if (!ctype_isRealBool (te2))
4828 message ("Right operand of %s is non-boolean (%t): %s",
4829 lltok_unparse (op), te2, exprNode_unparse (ret)),
4842 (cstring_makeLiteral
4843 ("There has been a problem in the parser. This usually results "
4844 "from using an old version of bison (1.25) to build LCLint. "
4845 "Please upgrade your bison implementation to version 1.28."));
4850 DPRINTF (("Return type: %s", ctype_unparse (tret)));
4853 exprNode_checkUse (ret, e1->sref, e1->loc);
4854 exprNode_mergeUSs (ret, e2);
4855 exprNode_checkUse (ret, e2->sref, e2->loc);
4861 exprNode_op (/*@only@*/ exprNode e1, /*@keep@*/ exprNode e2,
4862 /*@only@*/ lltok op)
4866 checkMacroParen (e1);
4867 checkMacroParen (e2);
4869 if (evaluationOrderUndefined (op) && context_maybeSet (FLG_EVALORDER))
4871 checkExpressionDefined (e1, e2, op);
4874 ret = exprNode_makeOp (e1, e2, op);
4879 void exprNode_checkAssignMod (exprNode e1, exprNode ret)
4882 ** This is somewhat bogus!
4884 ** Assigning to a nested observer in a non-observer datatype
4885 ** should not produce an error.
4888 sRef ref = exprNode_getSref (e1);
4890 DPRINTF (("Check assign mod: %s",
4891 sRef_unparseFull (ref)));
4893 if (sRef_isObserver (ref)
4894 || ((sRef_isFileStatic (ref) || sRef_isGlobal (ref))
4895 && ctype_isArray (ctype_realType (sRef_getType (ref)))))
4897 sRef base = sRef_getBase (ref);
4899 if (sRef_isValid (base) && sRef_isObserver (base))
4901 exprNode_checkModify (e1, ret);
4905 exprNode_checkModifyVal (e1, ret);
4910 exprNode_checkModify (e1, ret);
4915 exprNode_assign (/*@only@*/ exprNode e1,
4916 /*@only@*/ exprNode e2, /*@only@*/ lltok op)
4918 bool isalloc = FALSE;
4919 bool isjustalloc = FALSE;
4922 DPRINTF (("%s [%s] <- %s [%s]",
4923 exprNode_unparse (e1),
4924 ctype_unparse (e1->typ),
4925 exprNode_unparse (e2),
4926 ctype_unparse (e2->typ)));
4928 if (lltok_getTok (op) != TASSIGN)
4930 ret = exprNode_makeOp (e1, e2, op);
4934 ret = exprNode_createPartialCopy (e1);
4935 ret->kind = XPR_ASSIGN;
4936 ret->edata = exprData_makeOp (e1, e2, op);
4938 if (!exprNode_isError (e2))
4940 ret->sets = sRefSet_union (ret->sets, e2->sets);
4941 ret->msets = sRefSet_union (ret->msets, e2->msets);
4942 ret->uses = sRefSet_union (ret->uses, e2->uses);
4946 checkExpressionDefined (e1, e2, op);
4948 if (exprNode_isError (e1))
4950 if (!exprNode_isError (e2))
4952 ret->loc = fileloc_update (ret->loc, e2->loc);
4956 ret->loc = fileloc_update (ret->loc, g_currentloc);
4960 if (!exprNode_isError (e2))
4962 checkMacroParen (e2);
4965 if (exprNode_isDefined (e1))
4967 if (sRef_isMacroParamRef (e1->sref))
4969 if (context_inIterDef ())
4971 uentry ue = sRef_getUentry (e1->sref);
4973 if (uentry_isYield (ue))
4979 if (fileloc_isDefined (e1->loc))
4983 message ("Assignment to non-yield iter parameter: %q",
4984 sRef_unparse (e1->sref)),
4991 message ("Assignment to non-yield iter parameter: %q",
4992 sRef_unparse (e1->sref)),
4999 if (fileloc_isDefined (e1->loc))
5003 message ("Assignment to macro parameter: %q",
5004 sRef_unparse (e1->sref)),
5011 message ("Assignment to macro parameter: %q",
5012 sRef_unparse (e1->sref)),
5019 exprNode_checkAssignMod (e1, ret);
5022 if (exprNode_isDefined (e2))
5024 if (lltok_getTok (op) == TASSIGN)
5026 ctype te1 = exprNode_getType (e1);
5027 ctype te2 = exprNode_getType (e2);
5029 if (!ctype_forceMatch (te1, te2))
5031 if (exprNode_matchLiteral (te1, e2))
5039 message ("Assignment of %t to %t: %s %s %s",
5040 te2, te1, exprNode_unparse (e1),
5042 exprNode_unparse (e2)),
5048 exprNode_mergeUSs (ret, e2);
5049 exprNode_checkUse (ret, e2->sref, e2->loc);
5051 doAssign (e1, e2, FALSE);
5052 ret->sref = e1->sref;
5056 if (exprNode_isDefined (e2))
5058 exprNode_mergeUSs (ret, e2);
5059 exprNode_checkUse (ret, e2->sref, e2->loc);
5063 if (sRef_isPointer (e1->sref) && !sRef_isMacroParamRef (e1->sref))
5065 exprNode_checkUse (ret, sRef_getBase (e1->sref), e1->loc);
5068 isjustalloc = sRef_isJustAllocated (e1->sref);
5069 isalloc = sRef_isAllocated (e1->sref);
5071 if (sRef_isField (e1->sref))
5073 sRef root = sRef_getRootBase (sRef_getBase (e1->sref));
5075 if (!sRef_isAllocated (root) && !sRef_isMacroParamRef (root))
5077 exprNode_checkUse (ret, root, e1->loc);
5083 ** be careful! this defines e1->sref.
5086 if (!sRef_isMacroParamRef (e1->sref))
5088 exprNode_checkSet (ret, e1->sref);
5093 sRef_setAllocatedComplete (e1->sref, exprNode_isDefined (e2)
5094 ? e2->loc : e1->loc);
5100 sRef_setAllocatedShallowComplete (e1->sref, exprNode_loc (e2));
5109 exprNode_cond (/*@keep@*/ exprNode pred, /*@keep@*/ exprNode ifclause,
5110 /*@keep@*/ exprNode elseclause)
5114 if (!exprNode_isError (pred))
5116 ret = exprNode_createPartialCopy (pred);
5117 checkMacroParen (pred);
5118 exprNode_checkPred (cstring_makeLiteralTemp ("conditional"), pred);
5120 if (!exprNode_isError (ifclause))
5122 checkMacroParen (ifclause); /* update macro counts! */
5124 if (!exprNode_isError (elseclause))
5126 checkMacroParen (elseclause);
5128 if (!exprNode_matchTypes (ifclause, elseclause))
5131 (exprNode_getType (ifclause),
5133 exprNode_getType (elseclause),
5135 message ("Conditional clauses are not of same type: "
5137 exprNode_unparse (ifclause),
5138 exprNode_getType (ifclause),
5139 exprNode_unparse (elseclause),
5140 exprNode_getType (elseclause)),
5143 ret->sref = sRef_undefined;
5144 ret->typ = ctype_unknown;
5149 /* for now...should merge the states */
5150 ret->sref = ifclause->sref;
5151 ret->typ = ifclause->typ;
5153 if (exprNode_isNullValue (ifclause))
5155 ret->typ = elseclause->typ;
5159 exprNode_checkUse (ret, pred->sref, pred->loc);
5160 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
5161 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
5163 exprNode_mergeCondUSs (ret, ifclause, elseclause);
5168 ret->typ = ifclause->typ;
5170 exprNode_checkUse (pred, pred->sref, pred->loc);
5171 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
5173 exprNode_mergeCondUSs (ret, ifclause, exprNode_undefined);
5178 if (!exprNode_isError (elseclause))
5180 ret->typ = elseclause->typ;
5182 exprNode_checkUse (pred, pred->sref, pred->loc);
5183 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
5185 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
5189 else /* pred is error */
5191 if (!exprNode_isError (ifclause))
5193 ret = exprNode_createSemiCopy (ifclause);
5195 checkMacroParen (ifclause); /* update macro counts! */
5197 if (!exprNode_isError (elseclause))
5199 checkMacroParen (elseclause);
5201 ret->typ = ifclause->typ;
5203 if (!ctype_forceMatch (ifclause->typ, elseclause->typ))
5206 (exprNode_getType (ifclause),
5208 exprNode_getType (elseclause),
5210 message ("Conditional clauses are not of same type: "
5212 exprNode_unparse (ifclause),
5213 exprNode_getType (ifclause),
5214 exprNode_unparse (elseclause),
5215 exprNode_getType (elseclause)),
5218 ret->typ = ctype_unknown;
5222 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
5223 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
5225 exprNode_mergeCondUSs (ret, ifclause, elseclause);
5228 else if (!exprNode_isError (elseclause)) /* pred, if errors */
5230 ret = exprNode_createSemiCopy (ifclause);
5232 ret->typ = elseclause->typ;
5233 checkMacroParen (elseclause);
5235 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
5236 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
5238 else /* all errors! */
5240 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
5244 ret->kind = XPR_COND;
5245 ret->edata = exprData_makeCond (pred, ifclause, elseclause);
5247 if (exprNode_isDefined (ifclause) && exprNode_isDefined (elseclause))
5249 exprNode_combineControl (ret, ifclause, elseclause);
5256 exprNode_vaArg (/*@only@*/ lltok tok, /*@only@*/ exprNode arg, /*@only@*/ qtype qt)
5258 ctype totype = qtype_getType (qt);
5260 exprNode_createPartialLocCopy (arg, fileloc_copy (lltok_getLoc (tok)));
5264 ** check use of va_arg : <valist>, type -> type
5267 if (exprNode_isError (arg))
5272 targ = exprNode_getType (arg);
5275 ** arg should have be a pointer
5278 if (!ctype_isUA (targ) ||
5279 (!usymId_equal (ctype_typeId (targ),
5280 usymtab_getTypeId (cstring_makeLiteralTemp ("va_list")))))
5284 message ("First argument to va_arg is not a va_list (type %t): %s",
5285 targ, exprNode_unparse (arg)),
5289 exprNode_checkSet (ret, arg->sref);
5293 ** return type is totype
5297 ret->kind = XPR_VAARG;
5298 ret->edata = exprData_makeCast (tok, arg, qt);
5303 exprNode exprNode_labelMarker (/*@only@*/ cstring label)
5305 exprNode ret = exprNode_createPlain (ctype_undefined);
5306 ret->kind = XPR_LABEL;
5307 ret->edata = exprData_makeLiteral (label);
5308 ret->isJumpPoint = TRUE;
5310 return (ret); /* for now, ignore label */
5313 exprNode exprNode_notReached (/*@returned@*/ exprNode stmt)
5315 if (exprNode_isDefined (stmt))
5317 stmt->isJumpPoint = TRUE;
5319 /* This prevent stray no return path errors, etc. */
5320 stmt->exitCode = XK_MUSTEXIT;
5326 bool exprNode_isDefaultMarker (exprNode e)
5328 if (exprNode_isDefined (e))
5330 return (e->kind == XPR_DEFAULT || e->kind == XPR_FTDEFAULT);
5336 bool exprNode_isCaseMarker (exprNode e)
5338 if (exprNode_isDefined (e))
5340 return (e->kind == XPR_FTCASE || e->kind == XPR_CASE);
5346 bool exprNode_isLabelMarker (exprNode e)
5348 if (exprNode_isDefined (e))
5350 return (e->kind == XPR_LABEL);
5356 exprNode exprNode_caseMarker (/*@only@*/ exprNode test, bool fallThrough)
5358 exprNode ret = exprNode_createPartialCopy (test);
5360 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
5362 if (exprNode_isError (test)) {
5366 exprNode_checkUse (ret, test->sref, test->loc);
5368 usymtab_setExitCode (ret->exitCode);
5372 usymtab_setMustBreak ();
5375 ret->edata = exprData_makeSingle (test);
5376 ret->isJumpPoint = TRUE;
5382 exprNode exprNode_caseStatement (/*@only@*/ exprNode test, /*@only@*/ exprNode stmt, bool fallThrough)
5384 exprNode ret = exprNode_createPartialCopy (test);
5386 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
5387 ret->edata = exprData_makePair (test, stmt);
5388 ret->isJumpPoint = TRUE;
5390 if (exprNode_isError (test))
5395 exprNode_checkUse (ret, test->sref, test->loc);
5397 if (exprNode_isError (stmt))
5402 exprNode_mergeUSs (ret, stmt);
5404 ret->exitCode = stmt->exitCode;
5405 ret->mustBreak = stmt->mustBreak;
5406 ret->canBreak = stmt->canBreak;
5408 usymtab_setExitCode (ret->exitCode);
5412 usymtab_setMustBreak ();
5419 /*@notnull@*/ /*@only@*/ exprNode
5420 exprNode_defaultMarker (/*@only@*/ lltok def, bool fallThrough)
5422 exprNode ret = exprNode_createTok (def);
5424 ret->isJumpPoint = TRUE;
5425 ret->kind = fallThrough ? XPR_FTDEFAULT : XPR_DEFAULT;
5430 exprNode_mayEscape (exprNode e)
5432 if (exprNode_isDefined (e))
5434 return exitkind_couldEscape (e->exitCode);
5440 exprNode_mustBreak (exprNode e)
5442 if (exprNode_isDefined (e))
5444 return e->mustBreak;
5450 exprNode_mustEscape (exprNode e)
5452 if (exprNode_isDefined (e))
5454 return exitkind_mustEscape (e->exitCode) || exprNode_mustBreak (e);
5461 exprNode_errorEscape (exprNode e)
5463 if (exprNode_isDefined (e))
5465 return exitkind_isError (e->exitCode);
5471 exprNode exprNode_concat (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
5473 exprNode ret = exprNode_createPartialCopy (e1);
5475 ret->edata = exprData_makePair (e1, e2);
5476 ret->kind = XPR_STMTLIST;
5478 if (exprNode_isDefined (e1))
5480 ret->isJumpPoint = e1->isJumpPoint;
5481 ret->canBreak = e1->canBreak;
5485 if (exprNode_isDefined (e2))
5487 ret->loc = fileloc_update (ret->loc, e2->loc);
5491 if (exprNode_isDefined (e2))
5493 ret->exitCode = e2->exitCode;
5494 ret->mustBreak = e2->mustBreak;
5495 if (e2->canBreak) ret->canBreak = TRUE;
5499 ** if e1 must return, then e2 is unreachable!
5502 if (exprNode_isDefined (e1) && exprNode_isDefined (e2))
5504 if ((exprNode_mustEscape (e1) || exprNode_mustBreak (e1))
5505 && !(e2->isJumpPoint))
5507 if (context_getFlag (FLG_UNREACHABLE))
5511 if (e2->kind == XPR_STMT)
5513 nr = exprData_getSingle (e2->edata);
5516 if ((nr->kind == XPR_TOK
5517 && lltok_isSemi (exprData_getTok (nr->edata))))
5519 /* okay to have unreachable ";" */
5520 ret->exitCode = XK_MUSTEXIT;
5521 ret->canBreak = TRUE;
5525 if (optgenerror (FLG_UNREACHABLE,
5526 message ("Unreachable code: %s",
5527 exprNode_unparseFirst (nr)),
5530 ret->isJumpPoint = TRUE;
5531 ret->mustBreak = FALSE;
5532 ret->exitCode = XK_ERROR;
5533 DPRINTF (("Jump point: %s", exprNode_unparse (ret)));
5537 ret->exitCode = XK_MUSTEXIT;
5538 ret->canBreak = TRUE;
5546 if ((e2->kind == XPR_CASE || e2->kind == XPR_DEFAULT))
5549 ** We want a warning anytime we have:
5551 ** yyy; <<<- no break or return
5555 exprNode lastStmt = exprNode_lastStatement (e1);
5557 if (exprNode_isDefined (lastStmt)
5558 && !exprNode_mustEscape (lastStmt)
5559 && !exprNode_mustBreak (lastStmt)
5560 && !exprNode_isCaseMarker (lastStmt)
5561 && !exprNode_isDefaultMarker (lastStmt)
5562 && !exprNode_isLabelMarker (lastStmt))
5564 voptgenerror (FLG_CASEBREAK,
5566 ("Fall through case (no preceeding break)"),
5573 exprNode_mergeUSs (ret, e2);
5575 usymtab_setExitCode (ret->exitCode);
5579 usymtab_setMustBreak ();
5585 exprNode exprNode_createTok (/*@only@*/ lltok t)
5587 exprNode ret = exprNode_create (ctype_unknown);
5588 ret->kind = XPR_TOK;
5589 ret->edata = exprData_makeTok (t);
5593 exprNode exprNode_statement (/*@only@*/ exprNode e)
5595 if (!exprNode_isError (e))
5597 exprNode_checkStatement(e);
5600 return (exprNode_statementError (e));
5603 static exprNode exprNode_statementError (/*@only@*/ exprNode e)
5605 exprNode ret = exprNode_createPartialCopy (e);
5607 if (!exprNode_isError (e))
5609 if (e->kind != XPR_ASSIGN)
5611 exprNode_checkUse (ret, e->sref, e->loc);
5614 ret->exitCode = e->exitCode;
5615 ret->canBreak = e->canBreak;
5616 ret->mustBreak = e->mustBreak;
5619 ret->edata = exprData_makeSingle (e);
5620 ret->kind = XPR_STMT;
5625 exprNode exprNode_checkExpr (/*@returned@*/ exprNode e)
5627 if (!exprNode_isError (e))
5629 if (e->kind != XPR_ASSIGN)
5631 exprNode_checkUse (e, e->sref, e->loc);
5638 void exprNode_produceGuards (exprNode pred)
5640 if (!exprNode_isError (pred))
5642 if (ctype_isRealPointer (pred->typ))
5644 pred->guards = guardSet_addTrueGuard (pred->guards, pred->sref);
5647 exprNode_checkUse (pred, pred->sref, pred->loc);
5648 exprNode_resetSref (pred);
5652 exprNode exprNode_makeBlock (/*@only@*/ exprNode e)
5654 exprNode ret = exprNode_createPartialCopy (e);
5656 if (!exprNode_isError (e))
5658 ret->exitCode = e->exitCode;
5659 ret->canBreak = e->canBreak;
5660 ret->mustBreak = e->mustBreak;
5663 ret->edata = exprData_makeSingle (e);
5664 ret->kind = XPR_BLOCK;
5668 bool exprNode_isBlock (exprNode e)
5670 return (exprNode_isDefined (e)
5671 && ((e)->kind == XPR_BLOCK));
5674 bool exprNode_isAssign (exprNode e)
5676 if (exprNode_isDefined (e))
5678 return (e->kind == XPR_ASSIGN);
5684 bool exprNode_isEmptyStatement (exprNode e)
5686 return (exprNode_isDefined (e)
5687 && (e->kind == XPR_TOK)
5688 && (lltok_isSemi (exprData_getTok (e->edata))));
5691 exprNode exprNode_if (/*@only@*/ exprNode pred, /*@only@*/ exprNode tclause)
5694 bool emptyErr = FALSE;
5696 if (context_maybeSet (FLG_IFEMPTY))
5698 if (exprNode_isEmptyStatement (tclause))
5700 emptyErr = optgenerror (FLG_IFEMPTY,
5702 ("Body of if statement is empty"),
5703 exprNode_loc (tclause));
5707 if (!emptyErr && context_maybeSet (FLG_IFBLOCK))
5709 if (exprNode_isDefined (tclause)
5710 && !exprNode_isBlock (tclause))
5712 voptgenerror (FLG_IFBLOCK,
5714 ("Body of if statement is not a block: %s",
5715 exprNode_unparse (tclause)),
5716 exprNode_loc (tclause));
5720 if (exprNode_isError (pred))
5722 if (exprNode_isError (tclause))
5724 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
5728 ret = exprNode_createPartialCopy (tclause);
5733 if (exprNode_mustEscape (pred))
5737 message ("Predicate always exits: %s", exprNode_unparse (pred)),
5738 exprNode_loc (pred));
5741 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
5742 exprNode_checkUse (pred, pred->sref, pred->loc);
5744 if (!exprNode_isError (tclause))
5746 exprNode_mergeCondUSs (pred, tclause, exprNode_undefined);
5749 ret = exprNode_createPartialCopy (pred);
5753 ret->edata = exprData_makePair (pred, tclause);
5755 ret->exitCode = XK_UNKNOWN;
5757 if (exprNode_isDefined (tclause))
5759 ret->exitCode = exitkind_makeConditional (tclause->exitCode);
5760 ret->canBreak = tclause->canBreak;
5761 ret->sets = sRefSet_union (ret->sets, tclause->sets);
5762 ret->msets = sRefSet_union (ret->msets, tclause->msets);
5763 ret->uses = sRefSet_union (ret->uses, tclause->uses);
5766 ret->mustBreak = FALSE;
5771 exprNode exprNode_ifelse (/*@only@*/ exprNode pred,
5772 /*@only@*/ exprNode tclause,
5773 /*@only@*/ exprNode eclause)
5776 bool tEmptyErr = FALSE;
5777 bool eEmptyErr = FALSE;
5779 if (context_maybeSet (FLG_IFEMPTY))
5781 if (exprNode_isEmptyStatement (tclause))
5783 tEmptyErr = optgenerror
5786 ("Body of if clause of if statement is empty"),
5787 exprNode_loc (tclause));
5790 if (exprNode_isEmptyStatement (eclause))
5792 eEmptyErr = optgenerror
5795 ("Body of else clause of if statement is empty"),
5796 exprNode_loc (eclause));
5800 if (context_maybeSet (FLG_IFBLOCK))
5803 && exprNode_isDefined (tclause)
5804 && !exprNode_isBlock (tclause))
5806 voptgenerror (FLG_IFBLOCK,
5808 ("Body of if clause of if statement is not a block: %s",
5809 exprNode_unparse (tclause)),
5810 exprNode_loc (tclause));
5814 && exprNode_isDefined (eclause)
5815 && !exprNode_isBlock (eclause)
5816 && !(eclause->kind == XPR_IF)
5817 && !(eclause->kind == XPR_IFELSE))
5822 ("Body of else clause of if statement is not a block: %s",
5823 exprNode_unparse (eclause)),
5824 exprNode_loc (eclause));
5828 if (context_maybeSet (FLG_ELSEIFCOMPLETE))
5830 if (exprNode_isDefined (eclause)
5831 && (eclause->kind == XPR_IF))
5833 voptgenerror (FLG_ELSEIFCOMPLETE,
5834 message ("Incomplete else if logic (no final else): %s",
5835 exprNode_unparse (eclause)),
5836 exprNode_loc (eclause));
5840 if (exprNode_isError (pred))
5842 if (exprNode_isError (tclause))
5844 if (exprNode_isError (eclause))
5846 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
5850 ret = exprNode_createPartialCopy (eclause);
5855 ret = exprNode_createPartialCopy (tclause);
5858 else /* pred is okay */
5860 ret = exprNode_createPartialCopy (pred);
5862 if (exprNode_mustEscape (pred))
5866 message ("Predicate always exits: %s", exprNode_unparse (pred)),
5867 exprNode_loc (pred));
5870 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
5871 exprNode_checkUse (ret, pred->sref, pred->loc);
5873 exprNode_mergeCondUSs (ret, tclause, eclause);
5876 ret->kind = XPR_IFELSE;
5877 ret->edata = exprData_makeCond (pred, tclause, eclause);
5879 if (exprNode_isDefined (tclause) && exprNode_isDefined (eclause))
5881 exprNode_combineControl (ret, tclause, eclause);
5882 ret->loc = fileloc_update (ret->loc, eclause->loc);
5889 ** *allpaths <- TRUE iff all executions paths must go through the switch
5893 checkSwitchExpr (exprNode test, /*@dependent@*/ exprNode e, /*@out@*/ bool *allpaths)
5895 exprNodeSList el = exprNode_flatten (e);
5896 bool mustReturn = TRUE; /* find a branch that doesn't */
5897 bool thisReturn = FALSE;
5898 bool hasDefault = FALSE;
5899 bool hasAllMembers = FALSE;
5900 bool inSwitch = FALSE;
5901 bool isEnumSwitch = FALSE;
5902 bool canBreak = FALSE;
5903 bool fallThrough = FALSE;
5904 ctype ct = ctype_unknown;
5905 enumNameSList usedEnums;
5908 if (exprNode_isDefined (test))
5913 ttype = ctype_realType (ct);
5915 if (ctype_isEnum (ttype))
5917 isEnumSwitch = TRUE;
5918 enums = ctype_elist (ttype);
5919 usedEnums = enumNameSList_new ();
5923 exprNodeSList_elements (el, current)
5925 if (exprNode_isDefined (current))
5927 switch (current->kind)
5935 message ("Duplicate default cases in switch"),
5936 exprNode_loc (current));
5941 if (current->kind == XPR_DEFAULT || current->kind == XPR_FTDEFAULT)
5949 exprNode st = exprData_getSingle (current->edata);
5950 uentry ue = exprNode_getUentry (st);
5952 if (uentry_isValid (ue))
5954 cstring cname = uentry_rawName (ue);
5956 if (enumNameList_member (/*@-usedef@*/enums/*@=usedef@*/, cname))
5958 if (enumNameSList_member
5959 (/*@-usedef@*/usedEnums/*@=usedef@*/, cname))
5963 message ("Duplicate case in switch: %s",
5969 enumNameSList_addh (usedEnums, cname);
5976 message ("Case in switch not %s member: %s",
5977 ctype_unparse (ct), cname),
5984 if (inSwitch && !fallThrough)
5986 if (!thisReturn || canBreak)
5996 /*@switchbreak@*/ break;
5998 thisReturn = thisReturn || exprNode_mustEscape (current);
5999 canBreak = canBreak || current->canBreak;
6000 if (canBreak) fallThrough = FALSE;
6003 } end_exprNodeSList_elements;
6005 if (inSwitch) /* check the last one! */
6007 if (!thisReturn || canBreak)
6016 && (enumNameSList_size (/*@-usedef@*/usedEnums/*@=usedef@*/) !=
6017 enumNameList_size (/*@-usedef@*/enums/*@=usedef@*/)))
6019 enumNameSList unused = enumNameSList_subtract (enums, usedEnums);
6021 voptgenerror (FLG_MISSCASE,
6022 message ("Missing case%s in switch: %q",
6023 cstring_makeLiteralTemp
6024 ((enumNameSList_size (unused) > 1) ? "s" : ""),
6025 enumNameSList_unparse (unused)),
6028 enumNameSList_free (unused);
6032 hasAllMembers = TRUE;
6036 enumNameSList_free (usedEnums);
6040 *allpaths = hasDefault;
6043 exprNodeSList_free (el);
6044 return ((hasDefault || hasAllMembers) && mustReturn);
6047 exprNode exprNode_switch (/*@only@*/ exprNode e, /*@only@*/ exprNode s)
6049 exprNode ret = exprNode_createPartialCopy (e);
6052 DPRINTF (("Switch: %s", exprNode_unparse (s)));
6054 ret->kind = XPR_SWITCH;
6055 ret->edata = exprData_makePair (e, s);
6057 if (!exprNode_isError (s))
6059 exprNode fs = exprNode_firstStatement (s);
6060 ret->loc = fileloc_update (ret->loc, s->loc);
6062 if (exprNode_isUndefined (fs)
6063 || exprNode_isCaseMarker (fs) || exprNode_isLabelMarker (fs)
6064 || exprNode_isDefaultMarker (fs)) {
6067 voptgenerror (FLG_FIRSTCASE,
6069 ("Statement after switch is not a case: %s", exprNode_unparse (fs)),
6074 if (!exprNode_isError (e))
6076 if (checkSwitchExpr (e, s, &allpaths))
6078 ret->exitCode = XK_MUSTRETURN;
6082 ret->exitCode = e->exitCode;
6085 ret->canBreak = e->canBreak;
6086 ret->mustBreak = e->mustBreak;
6090 ** exprNode.c:3883,32: Variable allpaths used before definition
6097 DPRINTF (("Context exit switch!"));
6098 context_exitSwitch (ret, allpaths);
6099 DPRINTF (("Context exit switch done!"));
6104 static void checkInfiniteLoop (/*@notnull@*/ exprNode test,
6105 /*@notnull@*/ exprNode body)
6107 sRefSet tuses = test->uses;
6109 if (!sRefSet_isEmpty (test->uses))
6111 sRefSet sets = sRefSet_newCopy (body->sets);
6112 bool hasError = TRUE;
6113 bool innerState = FALSE;
6114 sRefSet tuncon = sRefSet_undefined;
6116 sets = sRefSet_union (sets, test->sets);
6117 sets = sRefSet_union (sets, body->msets);
6118 sets = sRefSet_union (sets, test->msets);
6120 sRefSet_allElements (tuses, el)
6122 if (sRef_isUnconstrained (el))
6124 tuncon = sRefSet_insert (tuncon, el);
6128 if (sRefSet_member (sets, el))
6135 if (sRef_isInternalState (el)
6136 || sRef_isFileStatic (sRef_getRootBase (el)))
6140 } end_sRefSet_allElements ;
6144 sRefSet suncon = sRefSet_undefined;
6145 bool sinner = FALSE;
6147 sRefSet_allElements (sets, el)
6149 if (sRef_isUnconstrained (el))
6151 suncon = sRefSet_insert (suncon, el);
6153 else if (sRef_isInternalState (el))
6161 } end_sRefSet_allElements ;
6163 if (sinner && innerState)
6167 else if (sRefSet_isEmpty (tuncon)
6168 && sRefSet_isEmpty (suncon))
6173 ("Suspected infinite loop. No value used in loop test (%q) "
6174 "is modified by test or loop body.",
6175 sRefSet_unparsePlain (tuses)),
6180 if (sRefSet_isEmpty (tuncon))
6184 message ("Suspected infinite loop. No condition values "
6185 "modified. Modification possible through "
6186 "unconstrained calls: %q",
6187 sRefSet_unparsePlain (suncon)),
6194 message ("Suspected infinite loop. No condition values "
6195 "modified. Possible undetected dependency through "
6196 "unconstrained calls in loop test: %q",
6197 sRefSet_unparsePlain (tuncon)),
6203 sRefSet_free (sets);
6207 exprNode exprNode_while (/*@keep@*/ exprNode t, /*@keep@*/ exprNode b)
6210 bool emptyErr = FALSE;
6212 if (context_maybeSet (FLG_WHILEEMPTY))
6214 if (exprNode_isEmptyStatement (b))
6216 emptyErr = optgenerror
6219 ("Body of while statement is empty"),
6224 if (!emptyErr && context_maybeSet (FLG_WHILEBLOCK))
6226 if (exprNode_isDefined (b)
6227 && !exprNode_isBlock (b))
6229 if (context_inIterDef ()
6230 && (b->kind == XPR_STMTLIST
6231 || b->kind == XPR_TOK))
6237 voptgenerror (FLG_WHILEBLOCK,
6239 ("Body of while statement is not a block: %s",
6240 exprNode_unparse (b)),
6246 if (exprNode_isError (t))
6248 if (exprNode_isError (b))
6250 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
6254 ret = exprNode_createPartialCopy (b);
6261 ret = exprNode_createPartialCopy (t);
6263 llassert (t->kind == XPR_WHILEPRED);
6265 test = exprData_getSingle (t->edata);
6267 if (!exprNode_isError (b) && exprNode_isDefined (test))
6269 if (context_maybeSet (FLG_INFLOOPS)
6270 || context_maybeSet (FLG_INFLOOPSUNCON))
6273 ** check that some variable in the predicate is set by the body
6274 ** if the predicate uses any variables
6277 checkInfiniteLoop (test, b);
6280 exprNode_mergeUSs (ret, b);
6282 if (exprNode_isDefined (b))
6284 ret->exitCode = exitkind_makeConditional (b->exitCode);
6289 ret->edata = exprData_makePair (t, b);
6290 ret->kind = XPR_WHILE;
6292 if (exprNode_isDefined (t) && exprNode_mustEscape (t))
6296 message ("Predicate always exits: %s", exprNode_unparse (t)),
6300 ret->exitCode = XK_NEVERESCAPE;
6303 ** If loop is infinite, and there is no break inside,
6304 ** exit code is never reach.
6307 if (exprNode_knownIntValue (t))
6309 if (!exprNode_isZero (t))
6311 if (exprNode_isDefined (b))
6315 /* Really, it means never reached. */
6316 ret->exitCode = XK_MUSTEXIT;
6326 ret->canBreak = FALSE;
6327 ret->mustBreak = FALSE;
6333 ** do { b } while (t);
6335 ** note: body passed as first argument
6338 exprNode exprNode_doWhile (/*@only@*/ exprNode b, /*@only@*/ exprNode t)
6342 if (exprNode_isError (t))
6344 if (exprNode_isError (b))
6346 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
6350 ret = exprNode_createPartialCopy (b);
6352 ret->exitCode = exitkind_makeConditional (b->exitCode);
6353 exprNode_checkUse (ret, b->sref, b->loc);
6354 ret->exitCode = b->exitCode;
6355 ret->canBreak = b->canBreak;
6356 ret->mustBreak = b->mustBreak;
6361 ret = exprNode_createPartialCopy (t);
6362 exprNode_checkPred (cstring_makeLiteralTemp ("while"), t);
6364 if (!exprNode_isError (b))
6367 ** forgot the copy's --- why wasn't this detected??
6370 ret->sets = sRefSet_copy (ret->sets, b->sets);
6371 ret->msets = sRefSet_copy (ret->msets, b->msets);
6372 ret->uses = sRefSet_copy (ret->uses, b->uses);
6374 /* left this out --- causes and aliasing bug (infinite loop)
6375 should be detected?? */
6377 exprNode_checkUse (ret, b->sref, b->loc);
6378 exprNode_mergeUSs (ret, t);
6379 exprNode_checkUse (ret, t->sref, t->loc);
6381 ret->exitCode = b->exitCode;
6382 ret->canBreak = b->canBreak;
6383 ret->mustBreak = b->mustBreak;
6387 context_exitDoWhileClause (t);
6389 ret->kind = XPR_DOWHILE;
6390 ret->edata = exprData_makePair (t, b);
6394 exprNode exprNode_for (/*@keep@*/ exprNode inc, /*@keep@*/ exprNode body)
6397 bool emptyErr = FALSE;
6399 if (context_maybeSet (FLG_FOREMPTY))
6401 if (exprNode_isEmptyStatement (body))
6403 emptyErr = optgenerror
6406 ("Body of for statement is empty"),
6407 exprNode_loc (body));
6411 if (!emptyErr && context_maybeSet (FLG_FORBLOCK))
6413 if (exprNode_isDefined (body)
6414 && !exprNode_isBlock (body))
6416 if (context_inIterDef ()
6417 && (body->kind == XPR_STMTLIST
6418 || body->kind == XPR_TOK))
6424 voptgenerror (FLG_FORBLOCK,
6426 ("Body of for statement is not a block: %s",
6427 exprNode_unparse (body)),
6428 exprNode_loc (body));
6434 ** for ud purposes: (alreadly) init -> test -> (now) LOOP: body + inc + test
6437 if (exprNode_isError (body))
6439 ret = exprNode_createPartialCopy (inc);
6443 ret = exprNode_createPartialCopy (body);
6445 ret->exitCode = exitkind_makeConditional (body->exitCode);
6447 exprNode_mergeUSs (inc, body);
6449 if (exprNode_isDefined (inc))
6453 context_setMessageAnnote (cstring_makeLiteral ("in post loop increment"));
6456 tmp = exprNode_effect (exprData_getTripleInc (inc->edata));
6457 exprNode_freeShallow (tmp);
6459 context_clearMessageAnnote ();
6460 context_setMessageAnnote (cstring_makeLiteral ("in post loop test"));
6462 tmp = exprNode_effect (exprData_getTripleTest (inc->edata));
6463 exprNode_freeShallow (tmp);
6465 context_clearMessageAnnote ();
6467 ret->uses = sRefSet_copy (ret->uses, inc->uses);
6468 ret->sets = sRefSet_copy (ret->sets, inc->sets);
6469 ret->msets = sRefSet_copy (ret->msets, inc->msets);
6473 ret->kind = XPR_FOR;
6474 ret->edata = exprData_makePair (inc, body);
6476 if (exprNode_isDefined (inc)) {
6477 exprNode test = exprData_getTripleTest (inc->edata);
6479 if (exprNode_isUndefined (test)) {
6480 if (exprNode_isDefined (body)) {
6481 if (!body->canBreak) {
6482 /* Really, it means never reached. */
6483 ret->exitCode = XK_MUSTEXIT;
6493 ** for (init; test; inc)
6496 ** while (test) { body; inc; }
6498 ** Now: check use of init (may set vars for test)
6499 ** check use of test
6503 /*@observer@*/ guardSet exprNode_getForGuards (exprNode pred)
6507 if (exprNode_isError (pred)) return guardSet_undefined;
6509 llassert (pred->kind == XPR_FORPRED);
6511 test = exprData_getTripleTest (pred->edata);
6513 if (!exprNode_isError (test))
6515 return (test->guards);
6518 return guardSet_undefined;
6521 exprNode exprNode_whilePred (/*@only@*/ exprNode test)
6523 exprNode ret = exprNode_createSemiCopy (test);
6525 if (exprNode_isDefined (test))
6527 exprNode_copySets (ret, test);
6528 exprNode_checkPred (cstring_makeLiteralTemp ("while"), test);
6529 exprNode_checkUse (ret, test->sref, test->loc);
6531 exprNode_produceGuards (test);
6533 ret->guards = guardSet_copy (test->guards);
6536 ret->edata = exprData_makeSingle (test);
6537 ret->kind = XPR_WHILEPRED;
6541 exprNode exprNode_forPred (/*@only@*/ exprNode init, /*@only@*/ exprNode test,
6542 /*@only@*/ exprNode inc)
6547 ** for ud purposes: init -> test -> LOOP: [ body, inc ]
6550 exprNode_checkPred (cstring_makeLiteralTemp ("for"), test);
6552 if (!exprNode_isError (inc))
6554 ret = exprNode_createPartialCopy (inc);
6558 if (!exprNode_isError (init))
6560 ret = exprNode_createPartialCopy (init);
6562 else if (!exprNode_isError (test))
6564 ret = exprNode_createPartialCopy (test);
6568 ret = exprNode_createUnknown ();
6572 exprNode_mergeUSs (ret, init);
6574 if (exprNode_isDefined (init))
6576 exprNode_checkUse (ret, init->sref, init->loc);
6579 exprNode_mergeUSs (ret, test);
6581 if (exprNode_isDefined (test))
6583 exprNode_checkUse (ret, test->sref, test->loc);
6586 ret->kind = XPR_FORPRED;
6587 ret->edata = exprData_makeFor (init, test, inc);
6591 /*@notnull@*/ /*@only@*/ exprNode exprNode_goto (/*@only@*/ cstring label)
6593 exprNode ret = exprNode_createUnknown ();
6595 if (context_inMacro ())
6597 voptgenerror (FLG_MACROSTMT,
6598 message ("Macro %s uses goto (not functional)",
6599 context_inFunctionName ()),
6603 ret->kind = XPR_GOTO;
6604 ret->edata = exprData_makeLiteral (label);
6605 ret->mustBreak = TRUE;
6606 ret->exitCode = XK_GOTO;
6607 ret->canBreak = TRUE;
6611 exprNode exprNode_continue (/*@only@*/ lltok l, int qcontinue)
6613 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
6615 ret->kind = XPR_CONTINUE;
6616 ret->edata = exprData_makeTok (l);
6617 ret->canBreak = TRUE;
6618 ret->mustBreak = TRUE;
6620 if (qcontinue == QSAFEBREAK)
6624 else if (qcontinue == QINNERCONTINUE)
6626 if (!context_inDeepLoop ())
6629 (FLG_LOOPLOOPCONTINUE,
6630 cstring_makeLiteral ("Continue statement marked with innercontinue "
6631 "is not inside a nested loop"),
6632 exprNode_loc (ret));
6635 else if (qcontinue == BADTOK)
6637 if (context_inDeepLoop ())
6640 (FLG_LOOPLOOPCONTINUE,
6641 cstring_makeLiteral ("Continue statement in nested loop"),
6642 exprNode_loc (ret));
6647 llbuglit ("exprNode_continue: bad qcontinue");
6653 exprNode exprNode_break (/*@only@*/ lltok l, int bqual)
6655 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
6656 clause breakClause = context_breakClause ();
6658 ret->kind = XPR_BREAK;
6659 ret->edata = exprData_makeTok (l);
6660 ret->canBreak = TRUE;
6661 ret->mustBreak = TRUE;
6663 if (breakClause == NOCLAUSE)
6667 cstring_makeLiteral ("Break not inside while, for or switch statement"),
6668 exprNode_loc (ret));
6672 if (bqual != BADTOK)
6679 if (breakClause == SWITCHCLAUSE)
6681 if (!context_inDeepSwitch ())
6683 voptgenerror (FLG_SYNTAX,
6685 ("Break preceded by innerbreak is not in a deep switch"),
6686 exprNode_loc (ret));
6691 if (!context_inDeepLoop ())
6693 voptgenerror (FLG_SYNTAX,
6695 ("Break preceded by innerbreak is not in a deep loop"),
6696 exprNode_loc (ret));
6701 if (breakClause == SWITCHCLAUSE)
6703 voptgenerror (FLG_SYNTAX,
6705 ("Break preceded by loopbreak is breaking a switch"),
6706 exprNode_loc (ret));
6710 if (breakClause != SWITCHCLAUSE)
6714 message ("Break preceded by switchbreak is breaking %s",
6715 cstring_makeLiteralTemp
6716 ((breakClause == WHILECLAUSE
6717 || breakClause == DOWHILECLAUSE) ? "a while loop"
6718 : (breakClause == FORCLAUSE) ? "a for loop"
6719 : (breakClause == ITERCLAUSE) ? "an iterator"
6721 exprNode_loc (ret));
6729 if (breakClause == SWITCHCLAUSE)
6731 clause nextBreakClause = context_nextBreakClause ();
6733 switch (nextBreakClause)
6735 case NOCLAUSE: break;
6741 (FLG_LOOPSWITCHBREAK,
6742 cstring_makeLiteral ("Break statement in switch inside loop"),
6743 exprNode_loc (ret));
6747 (FLG_SWITCHSWITCHBREAK,
6748 cstring_makeLiteral ("Break statement in switch inside switch"),
6749 exprNode_loc (ret));
6756 if (context_inDeepLoop ())
6760 cstring_makeLiteral ("Break statement in nested loop"),
6761 exprNode_loc (ret));
6765 if (context_inDeepLoopSwitch ())
6768 (FLG_SWITCHLOOPBREAK,
6769 cstring_makeLiteral ("Break statement in loop inside switch"),
6770 exprNode_loc (ret));
6780 exprNode exprNode_nullReturn (/*@only@*/ lltok t)
6782 fileloc loc = lltok_getLoc (t);
6783 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
6785 context_returnFunction ();
6786 exprChecks_checkNullReturn (loc);
6788 ret->kind = XPR_NULLRETURN;
6789 ret->edata = exprData_makeTok (t);
6790 ret->exitCode = XK_MUSTRETURN;
6794 exprNode exprNode_return (/*@only@*/ exprNode e)
6798 if (exprNode_isError (e))
6800 ret = exprNode_createUnknown ();
6804 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (e->loc));
6806 exprNode_checkUse (ret, e->sref, e->loc);
6807 exprNode_checkReturn (e);
6810 context_returnFunction ();
6811 ret->kind = XPR_RETURN;
6812 ret->edata = exprData_makeSingle (e);
6813 ret->exitCode = XK_MUSTRETURN;
6818 exprNode exprNode_comma (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
6822 if (exprNode_isError (e1))
6824 if (exprNode_isError (e2))
6826 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
6830 ret = exprNode_createPartialCopy (e2);
6831 exprNode_checkUse (ret, e2->sref, e2->loc);
6832 ret->sref = e2->sref;
6837 ret = exprNode_createPartialCopy (e1);
6839 exprNode_checkUse (ret, e1->sref, e1->loc);
6841 if (!exprNode_isError (e2))
6843 exprNode_mergeUSs (ret, e2);
6844 exprNode_checkUse (ret, e2->sref, e2->loc);
6845 ret->sref = e2->sref;
6849 ret->kind = XPR_COMMA;
6850 ret->edata = exprData_makePair (e1, e2);
6852 if (exprNode_isDefined (e1))
6854 if (exprNode_isDefined (e2))
6858 if (exprNode_mustEscape (e1) || e1->mustBreak)
6862 message ("Second clause of comma expression is unreachable: %s",
6863 exprNode_unparse (e2)),
6867 ret->exitCode = exitkind_combine (e1->exitCode, e2->exitCode);
6868 ret->mustBreak = e1->mustBreak || e2->mustBreak;
6869 ret->canBreak = e1->canBreak || e2->canBreak;
6873 if (exprNode_mustEscape (e1) || e1->mustBreak)
6877 message ("Second clause of comma expression is unreachable: %s",
6878 exprNode_unparse (e2)),
6882 ret->exitCode = e1->exitCode;
6883 ret->canBreak = e1->canBreak;
6888 if (exprNode_isDefined (e2))
6890 ret->exitCode = e2->exitCode;
6891 ret->mustBreak = e2->mustBreak;
6892 ret->canBreak = e2->canBreak;
6899 static bool exprNode_checkOneInit (/*@notnull@*/ exprNode el, exprNode val)
6901 ctype t1 = exprNode_getType (el);
6902 ctype t2 = exprNode_getType (val);
6903 bool hasError = FALSE;
6905 if (ctype_isUnknown (t1))
6907 voptgenerror (FLG_IMPTYPE,
6908 message ("Variable has unknown (implicitly int) type: %s",
6909 exprNode_unparse (el)),
6913 el->typ = ctype_int;
6916 if (exprNode_isDefined (val) && val->kind == XPR_INITBLOCK)
6918 exprNodeList vals = exprData_getArgs (val->edata);
6920 if (ctype_isRealAP (t1))
6925 exprNodeList_elements (vals, oneval)
6927 cstring istring = message ("%d", i);
6930 (exprNode_fakeCopy (el),
6931 exprNode_numLiteral (ctype_int, istring,
6932 fileloc_copy (el->loc), i));
6934 if (exprNode_isDefined (newel))
6936 if (exprNodeList_size (vals) == 1
6937 && ctype_isString (exprNode_getType (oneval))
6938 && ctype_isChar (exprNode_getType (newel)))
6940 exprNode_freeIniter (newel);
6944 if (exprNode_checkOneInit (newel, oneval))
6949 if (nerrors > 3 && exprNodeList_size (vals) > 6)
6952 (message ("Additional initialization errors "
6953 "for %s not reported",
6954 exprNode_unparse (el)),
6956 exprNode_freeIniter (newel);
6961 exprNode_freeIniter (newel);
6966 exprNode_freeIniter (newel);
6971 cstring_free (istring);
6974 } end_exprNodeList_elements;
6977 else if (ctype_isStruct (ctype_realType (t1)))
6979 uentryList fields = ctype_getFields (t1);
6982 if (uentryList_size (fields) != exprNodeList_size (vals))
6984 if (uentryList_size (fields) > exprNodeList_size (vals))
6986 hasError = optgenerror
6988 message ("Initializer block for "
6989 "%s has %d field%p, but %s has %d field%p: %q",
6990 exprNode_unparse (el),
6991 exprNodeList_size (vals),
6993 uentryList_size (fields),
6994 exprNodeList_unparse (vals)),
6999 hasError = optgenerror
7001 message ("Initializer block for "
7002 "%s has %d field%p, but %s has %d field%p: %q",
7003 exprNode_unparse (el),
7004 exprNodeList_size (vals),
7006 uentryList_size (fields),
7007 exprNodeList_unparse (vals)),
7013 exprNodeList_elements (vals, oneval)
7015 uentry thisfield = uentryList_getN (fields, i);
7017 exprNode_fieldAccess (exprNode_fakeCopy (el),
7018 uentry_getName (thisfield));
7020 if (exprNode_isDefined (newel))
7022 if (exprNode_checkOneInit (newel, oneval))
7027 exprNode_freeIniter (newel);
7031 } end_exprNodeList_elements;
7036 hasError = optgenerror
7038 message ("Initializer block used for "
7039 "%s where %t is expected: %s",
7040 exprNode_unparse (el), t1, exprNode_unparse (val)),
7046 if (exprNode_isDefined (val))
7048 doAssign (el, val, TRUE);
7050 if (!exprNode_matchType (t1, val))
7052 hasError = gentypeerror
7054 message ("Initial value of %s is type %t, "
7056 exprNode_unparse (el),
7057 t2, t1, exprNode_unparse (val)),
7066 exprNode exprNode_makeInitialization (/*@only@*/ idDecl t,
7067 /*@only@*/ exprNode e)
7069 uentry ue = usymtab_lookup (idDecl_observeId (t));
7070 bool isUsed = uentry_isUsed (ue);
7071 exprNode ret = exprNode_fromIdentifierAux (ue);
7072 ctype ct = ctype_realishType (ret->typ);
7075 if (ctype_isUnknown (ct))
7077 voptgenerror (FLG_IMPTYPE,
7078 message ("Variable has unknown (implicitly int) type: %s",
7079 idDecl_getName (t)),
7080 exprNode_isDefined (e) ? exprNode_loc (e) : g_currentloc);
7085 if (exprNode_isError (e))
7087 e = exprNode_createUnknown ();
7090 /* error: assume initializer is defined */
7091 sRef_setDefined (ret->sref, loc);
7095 loc = exprNode_loc (e);
7100 ** was addSafeUse --- what's the problem?
7102 ** int x = 3, y = x ?
7105 exprNode_checkUse (ret, e->sref, e->loc);
7107 if (ctype_isUnknown (e->typ) && uentry_isValid (ue))
7109 exprNode lhs = exprNode_createId (ue);
7112 ** static storage should be undefined before initializing
7115 if (uentry_isStatic (ue))
7117 sRef_setDefState (lhs->sref, SS_PARTIAL, fileloc_undefined);
7120 (void) exprNode_checkOneInit (lhs, e);
7122 if (uentry_isStatic (ue))
7124 sRef_setDefState (lhs->sref, SS_DEFINED, fileloc_undefined);
7127 exprNode_free (lhs);
7131 if (!exprNode_matchType (ct, e))
7133 if (exprNode_isZero (e) && ctype_isArrayPtr (ct))
7140 (exprNode_getType (e), e, exprNode_getType (ret), ret,
7142 ("Variable %s initialized to type %t, expects %t: %s",
7143 exprNode_unparse (ret), exprNode_getType (e),
7144 exprNode_getType (ret),
7145 exprNode_unparse (e)),
7151 if (uentry_isStatic (ue))
7153 sRef_setDefState (ret->sref, SS_PARTIAL, fileloc_undefined);
7156 doAssign (ret, e, TRUE);
7158 if (uentry_isStatic (ue))
7160 sRef_setDefState (ret->sref, SS_DEFINED, fileloc_undefined);
7164 if (context_inIterDef ())
7166 /* should check if it is yield */
7167 uentry_setUsed (ue, loc);
7171 if (!isUsed) /* could be @unused@-qualified variable */
7173 uentry_setNotUsed (ue);
7177 ret->exitCode = XK_NEVERESCAPE;
7178 ret->mustBreak = FALSE;
7181 ** Must be before new kind is assigned!
7184 exprData_free (ret->edata, ret->kind);
7186 ret->kind = XPR_INIT;
7187 ret->edata = exprData_makeInit (t, e);
7188 exprNode_mergeUSs (ret, e);
7192 exprNode exprNode_iter (/*@observer@*/ uentry name,
7193 /*@only@*/ exprNodeList alist,
7194 /*@only@*/ exprNode body,
7195 /*@observer@*/ uentry end)
7200 llassert (uentry_isValid (name));
7202 uentry_setUsed (name, exprNode_loc (body));
7204 ret = exprNode_createPartialCopy (body);
7205 iname = uentry_getName (name);
7207 if (uentry_isInvalid (end))
7210 message ("Iter %s not balanced with end_%s", iname, iname));
7214 cstring ename = uentry_getName (end);
7216 if (!cstring_equalPrefix (ename, "end_"))
7218 llerror (FLG_ITER, message ("Iter %s not balanced with end_%s: %s",
7219 iname, iname, ename));
7223 if (!cstring_equal (iname, cstring_suffix (ename, 4)))
7226 message ("Iter %s not balanced with end_%s: %s",
7227 iname, iname, ename));
7231 cstring_free (ename);
7234 context_exitIterClause (body);
7236 ret->kind = XPR_ITER;
7237 ret->edata = exprData_makeIter (name, alist, body, end);
7239 if (uentry_isIter (name))
7241 (void) checkArgsReal (name, body,
7242 uentry_getParams (name), alist, TRUE, ret);
7245 cstring_free (iname);
7251 exprNode_iterNewId (/*@only@*/ cstring s)
7253 exprNode e = exprNode_new ();
7254 uentry ue = uentryList_getN (uentry_getParams (getCurrentIter ()), iterParamNo ());
7256 llassert (processingIterVars ());
7258 e->loc = context_getSaveLocation ();
7260 if (fileloc_isUndefined (e->loc))
7262 fileloc_free (e->loc);
7263 e->loc = fileloc_copy (g_currentloc);
7266 e->uses = sRefSet_new ();
7267 e->sets = sRefSet_new ();
7268 e->msets = sRefSet_new ();
7270 e->val = multiVal_unknown ();
7271 e->guards = guardSet_new ();
7273 e->isJumpPoint = FALSE;
7274 e->exitCode = XK_NEVERESCAPE;
7276 /*> missing fields, detected by lclint <*/
7277 e->canBreak = FALSE;
7278 e->mustBreak = FALSE;
7279 e->etext = cstring_undefined;
7281 if (uentry_isYield (ue))
7283 uentry uue = uentry_makeVariable (s, uentry_getType (ue),
7284 fileloc_copy (e->loc),
7288 uue = usymtab_supEntrySrefReturn (uue);
7290 sr = uentry_getSref (uue);
7291 sRef_mergeStateQuiet (sr, uentry_getSref (ue));
7292 sr = uentry_getSref (uue);
7293 sRef_setDefined (sr, e->loc);
7295 e->typ = uentry_getType (uue);
7297 e->edata = exprData_makeId (uue);
7298 uentry_setUsed (uue, g_currentloc);
7304 sRef_setGlobalScope ();
7305 uue = uentry_makeVariableLoc (s, ctype_unknown);
7307 e->typ = ctype_unknown;
7308 e->edata = exprData_makeId (uue);
7310 uentry_setUsed (uue, e->loc);
7311 uentry_setHasNameError (uue);
7313 if (context_getFlag (FLG_REPEATUNRECOG))
7315 uentry_markOwned (uue);
7319 usymtab_supGlobalEntry (uue);
7322 sRef_clearGlobalScope ();
7324 voptgenerror (FLG_UNRECOG, message ("Unrecognized identifier: %s", s),
7334 exprNode_iterExpr (/*@returned@*/ exprNode e)
7336 if (!processingIterVars ())
7338 llcontbuglit ("checkIterParam: not in iter");
7342 if (uentry_isYield (uentryList_getN (uentry_getParams (getCurrentIter ()),
7345 if (exprNode_isDefined (e))
7347 if (fileloc_isDefined (e->loc))
7351 message ("Yield parameter is not simple identifier: %s",
7352 exprNode_unparse (e)),
7359 message ("Yield parameter is not simple identifier: %s",
7360 exprNode_unparse (e)),
7370 exprNode_iterId (/*@observer@*/ uentry c)
7374 llassert (processingIterVars ());
7376 ue = uentryList_getN (uentry_getParams (getCurrentIter ()),
7379 if (uentry_isYield (ue))
7381 ctype ct = uentry_getType (ue);
7382 exprNode e = exprNode_createPlain (ct);
7383 cstring name = uentry_getName (c);
7384 uentry le = uentry_makeVariable (name, ct, fileloc_undefined, FALSE);
7386 uentry_setUsed (ue, g_currentloc);
7387 uentry_setHasNameError (ue);
7389 cstring_free (name);
7392 e->edata = exprData_makeId (le);
7393 e->loc = context_getSaveLocation ();
7394 e->sref = uentry_getSref (le);
7396 usymtab_supEntrySref (le);
7398 if (!context_inHeader ())
7402 message ("Yield parameter shadows local declaration: %q",
7403 uentry_getName (c)),
7404 fileloc_isDefined (e->loc) ? e->loc : g_currentloc))
7406 uentry_showWhereDeclared (c);
7413 return (exprNode_fromIdentifierAux (c));
7416 exprNode exprNode_iterStart (/*@observer@*/ uentry name, /*@only@*/ exprNodeList alist)
7418 exprNode ret = exprNode_create (ctype_unknown);
7420 ret->kind = XPR_ITERCALL;
7421 ret->edata = exprData_makeIterCall (name, alist);
7423 if (uentry_isIter (name))
7425 uentryList params = uentry_getParams (name);
7427 if (context_inIterDef ()
7428 && uentryList_size (params) == exprNodeList_size (alist))
7432 exprNodeList_elements (alist, arg)
7434 uentry parg = uentryList_getN (params, i);
7436 if (uentry_isYield (parg))
7438 uentry ue = exprNode_getUentry (arg);
7440 if (uentry_isValid (ue))
7447 } end_exprNodeList_elements;
7450 (void) checkArgsReal (name, ret, params, alist, TRUE, ret);
7451 checkUnspecCall (ret, params, alist);
7457 /*@exposed@*/ sRef exprNode_getSref (exprNode e)
7459 if (exprNode_isDefined (e))
7462 if (e->sref == defref) /*@noaccess sRef@*/
7465 e->sref = sRef_makeUnknown ();
7466 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
7477 return sRef_undefined;
7481 /*@observer@*/ cstring
7482 exprNode_unparseFirst (exprNode e)
7484 if (exprNode_isDefined (e))
7488 if (e->kind == XPR_STMTLIST
7489 || e->kind == XPR_COMMA || e->kind == XPR_COND)
7491 exprNode first = exprData_getPairA (e->edata);
7493 if (exprNode_isDefined (first))
7495 return (exprNode_unparseFirst (exprData_getPairA (e->edata)));
7499 return (cstring_makeLiteralTemp ("..."));
7503 ret = cstring_elide (exprNode_unparse (e), 20);
7504 cstring_markOwned (ret);
7510 return cstring_makeLiteralTemp ("<error>");
7514 /*@observer@*/ cstring
7515 exprNode_unparse (exprNode e)
7517 if (exprNode_isError (e))
7519 return cstring_makeLiteralTemp ("<error>");
7522 if (cstring_isDefined (e->etext))
7528 cstring ret = exprNode_doUnparse (e);
7530 /*@-modifies@*/ /* benevolent */
7537 /*@observer@*/ fileloc
7538 exprNode_loc (exprNode e)
7540 if (exprNode_isError (e))
7542 return (g_currentloc);
7551 ** executes exprNode e
7552 ** recursively rexecutes as though in original parse using
7553 ** information in e->edata
7556 static /*@only@*/ exprNodeList exprNodeList_effect (exprNodeList e)
7558 exprNodeList ret = exprNodeList_new ();
7560 exprNodeList_elements (e, current)
7562 exprNodeList_addh (ret, exprNode_effect (current));
7563 } end_exprNodeList_elements;
7568 static /*@only@*/ exprNode exprNode_effect (exprNode e)
7569 /*@globals internalState@*/
7571 bool innerEffect = inEffect;
7577 context_clearJustPopped ();
7579 if (exprNode_isError (e))
7581 ret = exprNode_undefined;
7586 ** Turn off expose and dependent transfer checking.
7587 ** Need to pass exposed internal nodes,
7588 ** [ copying would be a waste! ]
7589 ** [ Actually, I think I wasted a lot more time than its worth ]
7590 ** [ trying to do this. ]
7594 /*@-observertrans@*/
7595 /*@-dependenttrans@*/
7602 ret = exprNode_addParens (exprData_getUopTok (data),
7603 exprNode_effect (exprData_getUopNode (data)));
7606 ret = exprNode_assign (exprNode_effect (exprData_getOpA (data)),
7607 exprNode_effect (exprData_getOpB (data)),
7608 exprData_getOpTok (data));
7611 ret = exprNode_undefined;
7614 ret = exprNode_functionCall (exprNode_effect (exprData_getFcn (data)),
7615 exprNodeList_effect (exprData_getArgs (data)));
7628 cstring id = exprData_getId (data);
7629 uentry ue = usymtab_lookupSafe (id);
7631 ret = exprNode_fromIdentifierAux (ue);
7632 ret->loc = fileloc_update (ret->loc, e->loc);
7639 ret = exprNode_arrayFetch (exprNode_effect (exprData_getPairA (data)),
7640 exprNode_effect (exprData_getPairB (data)));
7643 ret = exprNode_op (exprNode_effect (exprData_getOpA (data)),
7644 exprNode_effect (exprData_getOpB (data)),
7645 exprData_getOpTok (data));
7649 ret = exprNode_postOp (exprNode_effect (exprData_getUopNode (data)),
7650 exprData_getUopTok (data));
7653 ret = exprNode_preOp (exprNode_effect (exprData_getUopNode (data)),
7654 exprData_getUopTok (data));
7666 ret = exprNode_vaArg (exprData_getCastTok (data),
7667 exprNode_effect (exprData_getCastNode (data)),
7668 exprData_getCastType (data));
7672 ret = exprNode_cast (exprData_getCastTok (data),
7673 exprNode_effect (exprData_getCastNode (data)),
7674 exprData_getCastType (data));
7677 ret = exprNode_iterStart (exprData_getIterCallIter (data),
7679 (exprData_getIterCallArgs (data)));
7683 ret = exprNode_iter (exprData_getIterSname (data),
7684 exprNodeList_effect (exprData_getIterAlist (data)),
7685 exprNode_effect (exprData_getIterBody (data)),
7686 exprData_getIterEname (data));
7690 ret = exprNode_for (exprNode_effect (exprData_getPairA (data)),
7691 exprNode_effect (exprData_getPairB (data)));
7695 ret = exprNode_forPred (exprNode_effect (exprData_getTripleInit (data)),
7696 exprNode_effect (exprData_getTripleTest (data)),
7697 exprNode_effect (exprData_getTripleInc (data)));
7701 ret = exprNode_createTok (exprData_getTok (data));
7705 ret = exprNode_goto (exprData_getLiteral (data));
7706 ret->loc = fileloc_update (ret->loc, e->loc);
7710 ret = exprNode_continue (exprData_getTok (data), QSAFEBREAK);
7714 ret = exprNode_break (exprData_getTok (data), QSAFEBREAK);
7718 ret = exprNode_return (exprNode_effect (exprData_getSingle (data)));
7721 case XPR_NULLRETURN:
7722 ret = exprNode_nullReturn (exprData_getTok (data));
7726 ret = exprNode_comma (exprNode_effect (exprData_getPairA (data)),
7727 exprNode_effect (exprData_getPairB (data)));
7731 ret = exprNode_cond (exprNode_effect (exprData_getTriplePred (data)),
7732 exprNode_effect (exprData_getTripleTrue (data)),
7733 exprNode_effect (exprData_getTripleFalse (data)));
7736 ret = exprNode_if (exprNode_effect (exprData_getPairA (data)),
7737 exprNode_effect (exprData_getPairB (data)));
7741 ret = exprNode_ifelse (exprNode_effect (exprData_getTriplePred (data)),
7742 exprNode_effect (exprData_getTripleTrue (data)),
7743 exprNode_effect (exprData_getTripleFalse (data)));
7746 ret = exprNode_whilePred (exprData_getSingle (data));
7750 ret = exprNode_while (exprNode_effect (exprData_getPairA (data)),
7751 exprNode_effect (exprData_getPairB (data)));
7755 ret = exprNode_doWhile (exprNode_effect (exprData_getPairA (data)),
7756 exprNode_effect (exprData_getPairB (data)));
7760 ret = exprNode_makeBlock (exprNode_effect (exprData_getSingle (data)));
7764 ret = exprNode_statement (exprNode_effect (exprData_getSingle (data)));
7768 ret = exprNode_concat (exprNode_effect (exprData_getPairA (data)),
7769 exprNode_effect (exprData_getPairB (data)));
7774 ret = exprNode_caseMarker
7775 (exprNode_effect (exprData_getSingle (data)),
7781 ret = exprNode_createTok (exprData_getTok (data));
7785 ret = exprNode_switch (exprNode_effect (exprData_getPairA (data)),
7786 exprNode_effect (exprData_getPairB (data)));
7790 ret = exprNode_makeInitialization
7791 (exprData_getInitId (data),
7792 exprNode_effect (exprData_getInitNode (data)));
7796 ret = exprNode_fieldAccess (exprNode_effect (exprData_getFieldNode (data)),
7797 cstring_copy (exprData_getFieldName (data)));
7801 ret = exprNode_arrowAccess (exprNode_effect (exprData_getFieldNode (data)),
7802 cstring_copy (exprData_getFieldName (data)));
7805 case XPR_STRINGLITERAL:
7819 /*@=observertrans@*/
7821 /*@=dependenttrans@*/
7832 static /*@observer@*/ cstring exprNode_rootVarName (exprNode e)
7837 if (exprNode_isError (e))
7839 return cstring_undefined;
7847 ret = exprNode_rootVarName (exprData_getUopNode (data));
7850 ret = exprNode_rootVarName (exprData_getOpA (data));
7854 ret = exprData_getId (data);
7879 case XPR_NULLRETURN:
7902 case XPR_STRINGLITERAL:
7903 ret = cstring_undefined;
7910 static /*@only@*/ cstring exprNode_doUnparse (exprNode e)
7915 if (exprNode_isError (e))
7917 static /*@only@*/ cstring error = cstring_undefined;
7919 if (!cstring_isDefined (error))
7921 error = cstring_makeLiteral ("<error>");
7932 ret = message ("(%s)", exprNode_unparse (exprData_getUopNode (e->edata)));
7935 ret = message ("%s %s %s",
7936 exprNode_unparse (exprData_getOpA (data)),
7937 lltok_unparse (exprData_getOpTok (data)),
7938 exprNode_unparse (exprData_getOpB (data)));
7941 ret = message ("%s(%q)",
7942 exprNode_unparse (exprData_getFcn (data)),
7943 exprNodeList_unparse (exprData_getArgs (data)));
7946 ret = message ("{ %q }", exprNodeList_unparse (exprData_getArgs (data)));
7949 ret = cstring_undefined;
7952 ret = message ("%s:", exprData_getId (data));
7956 ret = cstring_copy (exprData_getId (data));
7959 ret = message ("%s[%s]", exprNode_unparse (exprData_getPairA (data)),
7960 exprNode_unparse (exprData_getPairB (data)));
7963 ret = message ("<body>");
7966 ret = message ("%s %s %s",
7967 exprNode_unparse (exprData_getOpA (data)),
7968 lltok_unparse (exprData_getOpTok (data)),
7969 exprNode_unparse (exprData_getOpB (data)));
7973 ret = message ("%s%s",
7974 lltok_unparse (exprData_getUopTok (data)),
7975 exprNode_unparse (exprData_getUopNode (data)));
7979 ret = message ("%s%s",
7980 exprNode_unparse (exprData_getUopNode (data)),
7981 lltok_unparse (exprData_getUopTok (data)));
7985 ret = message ("offsetof(%s,%q)",
7986 ctype_unparse (qtype_getType (exprData_getOffsetType (data))),
7987 cstringList_unparseSep (exprData_getOffsetName (data), cstring_makeLiteralTemp (".")));
7991 ret = message ("sizeof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
7995 ret = message ("sizeof(%s)", exprNode_unparse (exprData_getSingle (data)));
7999 ret = message ("alignof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
8003 ret = message ("alignof(%s)", exprNode_unparse (exprData_getSingle (data)));
8007 ret = message ("va_arg(%s, %q)",
8008 exprNode_unparse (exprData_getCastNode (data)),
8009 qtype_unparse (exprData_getCastType (data)));
8013 ret = message ("%q(%q)",
8014 uentry_getName (exprData_getIterCallIter (data)),
8015 exprNodeList_unparse (exprData_getIterCallArgs (data)));
8018 ret = message ("%q(%q) %s %q",
8019 uentry_getName (exprData_getIterSname (data)),
8020 exprNodeList_unparse (exprData_getIterAlist (data)),
8021 exprNode_unparse (exprData_getIterBody (data)),
8022 uentry_getName (exprData_getIterEname (data)));
8025 ret = message ("(%q)%s",
8026 qtype_unparse (exprData_getCastType (data)),
8027 exprNode_unparse (exprData_getCastNode (data)));
8031 ret = message ("%s %s",
8032 exprNode_unparse (exprData_getPairA (data)),
8033 exprNode_unparse (exprData_getPairB (data)));
8037 ret = message ("for (%s; %s; %s)",
8038 exprNode_unparse (exprData_getTripleInit (data)),
8039 exprNode_unparse (exprData_getTripleTest (data)),
8040 exprNode_unparse (exprData_getTripleInc (data)));
8044 ret = message ("goto %s", exprData_getLiteral (data));
8048 ret = cstring_makeLiteral ("continue");
8052 ret = cstring_makeLiteral ("break");
8056 ret = message ("return %s", exprNode_unparse (exprData_getSingle (data)));
8059 case XPR_NULLRETURN:
8060 ret = cstring_makeLiteral ("return");
8064 ret = message ("%s, %s",
8065 exprNode_unparse (exprData_getPairA (data)),
8066 exprNode_unparse (exprData_getPairB (data)));
8070 ret = message ("%s ? %s : %s",
8071 exprNode_unparse (exprData_getTriplePred (data)),
8072 exprNode_unparse (exprData_getTripleTrue (data)),
8073 exprNode_unparse (exprData_getTripleFalse (data)));
8076 ret = message ("if (%s) %s",
8077 exprNode_unparse (exprData_getPairA (data)),
8078 exprNode_unparse (exprData_getPairB (data)));
8082 ret = message ("if (%s) %s else %s",
8083 exprNode_unparse (exprData_getTriplePred (data)),
8084 exprNode_unparse (exprData_getTripleTrue (data)),
8085 exprNode_unparse (exprData_getTripleFalse (data)));
8088 ret = message ("while (%s) %s",
8089 exprNode_unparse (exprData_getPairA (data)),
8090 exprNode_unparse (exprData_getPairB (data)));
8094 ret = cstring_copy (exprNode_unparse (exprData_getSingle (data)));
8098 ret = cstring_copy (lltok_unparse (exprData_getTok (data)));
8102 ret = message ("do { %s } while (%s)",
8103 exprNode_unparse (exprData_getPairB (data)),
8104 exprNode_unparse (exprData_getPairA (data)));
8108 ret = message ("{ %s }", exprNode_unparseFirst (exprData_getSingle (data)));
8112 ret = cstring_copy (exprNode_unparse (exprData_getSingle (data)));
8116 ret = message ("%s; %s",
8117 exprNode_unparse (exprData_getPairA (data)),
8118 exprNode_unparse (exprData_getPairB (data)));
8123 ret = cstring_makeLiteral ("default:");
8127 ret = message ("switch (%s) %s",
8128 exprNode_unparse (exprData_getPairA (data)),
8129 exprNode_unparse (exprData_getPairB (data)));
8134 ret = message ("case %s:",
8135 exprNode_unparse (exprData_getSingle (data)));
8139 ret = message ("%s = %s",
8140 idDecl_getName (exprData_getInitId (data)),
8141 exprNode_unparse (exprData_getInitNode (data)));
8145 ret = message ("%s.%s",
8146 exprNode_unparse (exprData_getFieldNode (data)),
8147 exprData_getFieldName (data));
8151 ret = message ("%s->%s",
8152 exprNode_unparse (exprData_getFieldNode (data)),
8153 exprData_getFieldName (data));
8156 case XPR_STRINGLITERAL:
8157 ret = cstring_copy (exprData_getLiteral (data));
8161 ret = cstring_copy (exprData_getLiteral (data));
8165 ret = cstring_makeLiteral ("<node>");
8173 exprNode_isCharLit (exprNode e)
8175 if (exprNode_isDefined (e))
8177 return (multiVal_isChar (exprNode_getValue (e)));
8186 exprNode_isNumLit (exprNode e)
8188 if (exprNode_isDefined (e))
8190 return (multiVal_isInt (exprNode_getValue (e)));
8199 exprNode_isFalseConstant (exprNode e)
8201 if (exprNode_isDefined (e))
8203 cstring s = exprNode_rootVarName (e);
8205 if (cstring_equal (s, context_getFalseName ()))
8215 exprNode_matchLiteral (ctype expected, exprNode e)
8217 if (exprNode_isDefined (e))
8219 multiVal m = exprNode_getValue (e);
8221 if (multiVal_isDefined (m))
8223 if (multiVal_isInt (m))
8225 long int val = multiVal_forceInt (m);
8227 if (ctype_isDirectBool (ctype_realishType (expected)))
8231 return FALSE; /* really?! return TRUE; allow use of 0 for FALSE */
8239 if (ctype_isRealInt (expected))
8242 ** unsigned <- [ constant >= 0 is okay ]
8245 if (ctype_isUnsigned (expected))
8254 ** No checks on sizes of integers...maybe add
8258 DPRINTF (("Here: %s => %s", exprNode_unparse (e), ctype_unparse (expected)));
8259 DPRINTF (("Type: %s / %s", ctype_unparse (exprNode_getType (e)),
8260 bool_unparse (ctype_isInt (exprNode_getType (e)))));
8262 if (context_getFlag (FLG_NUMLITERAL)
8263 && (ctype_isRegularInt (exprNode_getType (e)) || val == 0)) {
8269 return FALSE; /* evs 2000-05-17: previously, always returned TRUE */
8273 else if (ctype_isChar (expected))
8277 else if (ctype_isArrayPtr (expected))
8281 else if (ctype_isAnyFloat (expected))
8283 return (context_getFlag (FLG_NUMLITERAL));
8290 else if (multiVal_isDouble (m))
8292 if (ctype_isAnyFloat (expected))
8297 else if (multiVal_isChar (m))
8299 char val = multiVal_forceChar (m);
8301 if (ctype_isChar (expected))
8303 if (ctype_isUnsigned (expected) && ((int)val) < 0)
8324 exprNode_matchType (ctype expected, exprNode e)
8328 if (!exprNode_isDefined (e)) return TRUE;
8330 actual = ctype_realishType (exprNode_getType (e));
8332 if (ctype_match (ctype_realishType (expected), actual))
8337 llassert (!exprNode_isError (e));
8338 return (exprNode_matchLiteral (expected, e));
8342 exprNode_matchTypes (exprNode e1, exprNode e2)
8347 if (!exprNode_isDefined (e1)) return TRUE;
8348 if (!exprNode_isDefined (e2)) return TRUE;
8351 ** realish type --- keep bools, bools
8354 t1 = ctype_realishType (exprNode_getType (e1));
8355 t2 = ctype_realishType (exprNode_getType (e2));
8357 if (ctype_match (t1, t2))
8362 return (exprNode_matchLiteral (t1, e2) || exprNode_matchLiteral (t2, e1));
8370 exprNode_matchArgType (ctype ct, exprNode e)
8374 if (!exprNode_isDefined (e))
8379 et = ctype_realType (exprNode_getType (e));
8381 if (ctype_matchArg (ct, et)) return TRUE;
8383 llassert (!exprNode_isError (e));
8384 return (exprNode_matchLiteral (ct, e));
8387 static /*@only@*/ exprNodeSList
8388 exprNode_flatten (/*@dependent@*/ exprNode e) /*@*/
8390 if (exprNode_isDefined (e))
8392 if (e->kind == XPR_STMTLIST)
8394 return (exprNodeSList_append
8395 (exprNode_flatten (exprData_getPairA (e->edata)),
8396 exprNode_flatten (exprData_getPairB (e->edata))));
8398 else if (e->kind == XPR_BLOCK)
8400 return (exprNode_flatten (exprData_getSingle (e->edata)));
8404 return (exprNodeSList_singleton (e));
8408 return exprNodeSList_new ();
8411 static /*@exposed@*/ exprNode
8412 exprNode_lastStatement (/*@returned@*/ exprNode e)
8414 if (exprNode_isDefined (e))
8416 if (e->kind == XPR_STMTLIST)
8418 exprNode b = exprData_getPairB (e->edata);
8420 if (exprNode_isDefined (b))
8422 return exprNode_lastStatement (b);
8426 return exprNode_lastStatement (exprData_getPairA (e->edata));
8429 else if (e->kind == XPR_BLOCK)
8431 return (exprNode_lastStatement (exprData_getSingle (e->edata)));
8439 return exprNode_undefined;
8442 static /*@exposed@*/ exprNode
8443 exprNode_firstStatement (/*@returned@*/ exprNode e)
8445 if (exprNode_isDefined (e))
8447 if (e->kind == XPR_STMTLIST)
8449 exprNode b = exprData_getPairA (e->edata);
8451 if (exprNode_isDefined (b))
8453 return exprNode_firstStatement (b);
8457 return exprNode_firstStatement (exprData_getPairB (e->edata));
8460 else if (e->kind == XPR_BLOCK)
8462 return (exprNode_firstStatement (exprData_getSingle (e->edata)));
8470 return exprNode_undefined;
8474 exprNode_mergeUSs (exprNode res, exprNode other)
8476 if (exprNode_isDefined (res) && exprNode_isDefined (other))
8478 res->msets = sRefSet_union (res->msets, other->msets);
8479 res->sets = sRefSet_union (res->sets, other->sets);
8480 res->uses = sRefSet_union (res->uses, other->uses);
8485 exprNode_mergeCondUSs (exprNode res, exprNode other1, exprNode other2)
8487 if (exprNode_isDefined (res))
8489 if (exprNode_isDefined (other1))
8491 res->sets = sRefSet_union (res->sets, other1->sets);
8492 res->msets = sRefSet_union (res->msets, other1->msets);
8493 res->uses = sRefSet_union (res->uses, other1->uses);
8495 if (exprNode_isDefined (other2))
8497 res->sets = sRefSet_union (res->sets, other2->sets);
8498 res->msets = sRefSet_union (res->msets, other2->msets);
8499 res->uses = sRefSet_union (res->uses, other2->uses);
8507 ** Reports errors is s is not defined.
8511 exprNode_addUse (exprNode e, sRef s)
8513 if (exprNode_isDefined (e))
8515 e->uses = sRefSet_insert (e->uses, s);
8520 exprNode_checkUse (exprNode e, sRef s, fileloc loc)
8522 if (sRef_isKnown (s) && !sRef_isConst (s))
8525 ** need to check all outer types are useable
8528 DPRINTF (("Check use: %s / %s",
8529 exprNode_unparse (e), sRef_unparse (s)));
8531 exprNode_addUse (e, s);
8533 if (!context_inProtectVars ())
8536 ** only report the deepest error
8539 sRef errorRef = sRef_undefined;
8540 sRef lastRef = sRef_undefined;
8541 bool deadRef = FALSE;
8542 bool unuseable = FALSE;
8543 bool errorMaybe = FALSE;
8545 while (sRef_isValid (s) && sRef_isKnown (s))
8547 ynm readable = sRef_isReadable (s);
8549 if (!(ynm_toBoolStrict (readable)))
8551 if (ynm_isMaybe (readable))
8555 deadRef = sRef_isPossiblyDead (errorRef);
8556 unuseable = sRef_isUnuseable (errorRef);
8563 deadRef = sRef_isDead (errorRef);
8564 unuseable = sRef_isUnuseable (errorRef);
8568 if (!sRef_isPartial (s))
8570 sRef_setDefined (s, fileloc_undefined);
8574 s = sRef_getBaseSafe (s);
8577 if (sRef_isValid (errorRef))
8579 if (sRef_isValid (lastRef) && sRef_isField (lastRef)
8580 && sRef_isPointer (errorRef))
8587 if (sRef_isThroughArrayFetch (errorRef))
8590 (FLG_STRICTUSERELEASED,
8591 message ("%q %q may be used after being released",
8592 sRef_unparseKindNamePlain (errorRef),
8593 sRef_unparse (errorRef)),
8596 sRef_showRefKilled (errorRef);
8598 if (sRef_isKept (errorRef))
8600 sRef_clearAliasState (errorRef, loc);
8606 DPRINTF (("HERE: %s", sRef_unparse (errorRef)));
8610 message ("%q %q %qused after being released",
8611 sRef_unparseKindNamePlain (errorRef),
8612 sRef_unparse (errorRef),
8613 cstring_makeLiteral (errorMaybe
8617 sRef_showRefKilled (errorRef);
8619 if (sRef_isKept (errorRef))
8621 sRef_clearAliasState (errorRef, loc);
8630 message ("%q %q%qused in inconsistent state",
8631 sRef_unparseKindName (errorRef),
8632 sRef_unparseOpt (errorRef),
8633 cstring_makeLiteral (errorMaybe ? "may be " : "")),
8636 sRef_showStateInconsistent (errorRef);
8641 DPRINTF (("HERE: %s", sRef_unparse (errorRef)));
8645 message ("%q %q%qused before definition",
8646 sRef_unparseKindName (errorRef),
8647 sRef_unparseOpt (errorRef),
8648 cstring_makeLiteral (errorMaybe ? "may be " : "")),
8652 sRef_setDefined (errorRef, loc);
8654 if (sRef_isAddress (errorRef))
8656 sRef_setDefined (sRef_getRootBase (errorRef), loc);
8658 } /* end is error */
8666 checkSafeUse (exprNode e, sRef s)
8668 if (exprNode_isDefined (e) && sRef_isKnown (s))
8670 e->uses = sRefSet_insert (e->uses, s);
8675 exprNode_checkSetAny (exprNode e, /*@dependent@*/ cstring name)
8677 if (exprNode_isDefined (e))
8679 e->sets = sRefSet_insert (e->sets, sRef_makeUnconstrained (name));
8684 exprNode_checkSet (exprNode e, sRef s)
8686 sRef defines = sRef_undefined;
8688 if (sRef_isValid (s) && !sRef_isNothing (s))
8690 uentry ue = sRef_getBaseUentry (s);
8692 if (uentry_isValid (ue))
8694 uentry_setLset (ue);
8697 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
8699 voptgenerror (FLG_USEDEF,
8700 message ("Attempt to set unuseable storage: %q",
8705 if (sRef_isMeaningful (s))
8708 if (sRef_isDead (s))
8710 sRef base = sRef_getBaseSafe (s);
8712 if (sRef_isValid (base)
8713 && sRef_isDead (base))
8715 sRef_setPartial (s, exprNode_loc (e));
8718 defines = s; /* okay - modifies for only param */
8720 else if (sRef_isPartial (s))
8722 sRef eref = exprNode_getSref (e);
8724 if (!sRef_isPartial (eref))
8727 ** should do something different here???
8730 sRef_setDefinedComplete (eref, exprNode_loc (e));
8734 sRef_setPartialDefinedComplete (eref, exprNode_loc (e));
8737 if (sRef_isMeaningful (eref))
8746 else if (sRef_isAllocated (s))
8748 sRef eref = exprNode_getSref (e);
8751 if (!sRef_isAllocated (eref))
8753 sRef_setDefinedComplete (eref, exprNode_loc (e));
8757 sRef base = sRef_getBaseSafe (eref);
8759 if (sRef_isValid (base))
8761 sRef_setPdefined (base, exprNode_loc (e));
8769 sRef_setDefinedNCComplete (s, exprNode_loc (e));
8774 else /* not meaningful...but still need to insert it */
8780 if (exprNode_isDefined (e) && sRef_isValid (defines))
8782 e->sets = sRefSet_insert (e->sets, defines);
8787 exprNode_checkMSet (exprNode e, sRef s)
8789 if (sRef_isValid (s) && !sRef_isNothing (s))
8791 uentry ue = sRef_getBaseUentry (s);
8793 if (uentry_isValid (ue))
8795 uentry_setLset (ue);
8798 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
8800 voptgenerror (FLG_USEDEF,
8801 message ("Attempt to set unuseable storage: %q", sRef_unparse (s)),
8805 if (sRef_isMeaningful (s))
8807 sRef_setDefinedComplete (s, exprNode_loc (e));
8810 if (exprNode_isDefined (e))
8812 e->msets = sRefSet_insert (e->msets, s);
8818 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode fcn, uentryList params, exprNodeList args)
8820 checkAnyCall (fcn, cstring_undefined, params, args,
8821 FALSE, sRefSet_undefined, FALSE, 0);
8825 checkOneArg (uentry ucurrent, /*@notnull@*/ exprNode current,
8826 /*@dependent@*/ exprNode fcn, bool isSpec, int argno, int totargs)
8830 if (uentry_isYield (ucurrent))
8832 sRef_setDefined (exprNode_getSref (current), exprNode_loc (current));
8833 exprNode_checkSet (current, current->sref);
8837 if (uentry_isSefParam (ucurrent))
8839 sRefSet sets = current->sets;
8840 sRef ref = exprNode_getSref (current);
8842 if (sRef_isMacroParamRef (ref))
8844 uentry ue = sRef_getUentry (ref);
8846 if (!uentry_isSefParam (ue))
8851 ("Parameter %d to %s is declared sef, but "
8852 "the argument is a macro parameter declared "
8854 argno, exprNode_unparse (fcn),
8855 exprNode_unparse (current)),
8856 exprNode_loc (current));
8860 if (!sRefSet_isEmpty (sets))
8862 sRefSet reported = sRefSet_undefined;
8864 sRefSet_realElements (current->sets, el)
8866 if (sRefSet_isSameNameMember (reported, el))
8868 ; /* don't report again */
8872 if (sRef_isUnconstrained (el))
8877 ("Parameter %d to %s is declared sef, but "
8878 "the argument calls unconstrained function %s "
8879 "(no guarantee it will not modify something): %s",
8880 argno, exprNode_unparse (fcn),
8881 sRef_unconstrainedName (el),
8882 exprNode_unparse (current)),
8883 exprNode_loc (current));
8890 ("Parameter %d to %s is declared sef, but "
8891 "the argument may modify %q: %s",
8892 argno, exprNode_unparse (fcn),
8894 exprNode_unparse (current)),
8895 exprNode_loc (current));
8898 } end_sRefSet_realElements;
8902 checkPassTransfer (current, ucurrent, isSpec, fcn, argno, totargs);
8903 exprNode_mergeUSs (fcn, current);
8908 checkAnyCall (/*@dependent@*/ exprNode fcn,
8909 /*@dependent@*/ cstring fname,
8912 bool hasMods, sRefSet mods,
8917 int nargs = exprNodeList_size (args);
8922 ** concat all args ud's to f, add each arg sref as a use unless
8923 ** it was specified as "out", in which case it is a def.
8926 uentryList_reset (pn);
8931 ** if paramn is only or unique, no other arg may alias argn
8934 exprNodeList_elements (args, current)
8938 if (exprNode_isDefined (current))
8940 if ((!uentryList_isUndefined (pn) && !uentryList_isFinished (pn)))
8942 uentry ucurrent = uentryList_current (pn);
8944 if (specialArgs == 0
8945 || (paramno < specialArgs))
8947 checkOneArg (ucurrent, current, fcn, isSpec, paramno, nargs);
8949 if (context_maybeSet (FLG_ALIASUNIQUE))
8951 if (uentry_isOnly (ucurrent)
8952 || uentry_isUnique (ucurrent))
8954 checkUniqueParams (fcn, current, args,
8960 else /* uentry is undefined */
8962 if (specialArgs == 0)
8964 exprNode_checkUseParam (current);
8967 exprNode_mergeUSs (fcn, current);
8970 uentryList_advanceSafe (pn);
8971 } end_exprNodeList_elements;
8977 sRefSet_allElements (mods, s)
8980 sRef rb = sRef_getRootBase (s);
8982 if (sRef_isGlobal (rb))
8984 context_usedGlobal (rb);
8987 fb = sRef_fixBaseParam (s, args);
8989 if (!sRef_isMacroParamRef (fb))
8991 if (sRef_isNothing (fb))
8997 if (sRef_isValid (fb))
8999 uentry ue = sRef_getBaseUentry (s);
9001 if (uentry_isValid (ue))
9003 uentry_setLset (ue);
9007 fcn->sets = sRefSet_insert (fcn->sets, fb);
9010 sRef_clearDerivedComplete (s);
9011 } end_sRefSet_allElements;
9017 if (context_hasMods ())
9019 if (context_maybeSet (FLG_MODUNCON))
9023 message ("Undetected modification possible "
9024 "from call to unconstrained function %s: %s",
9026 exprNode_unparse (fcn)),
9027 exprNode_loc (fcn));
9032 if (context_maybeSet (FLG_MODUNCONNOMODS)
9033 && !(context_inIterDef () || context_inIterEnd ()))
9036 (FLG_MODUNCONNOMODS,
9037 message ("Undetected modification possible "
9038 "from call to unconstrained function %s: %s",
9040 exprNode_unparse (fcn)),
9041 exprNode_loc (fcn));
9045 exprNode_checkSetAny (fcn, fname);
9049 void exprNode_checkUseParam (exprNode current)
9051 if (exprNode_isDefined (current))
9053 exprNode_checkUse (current, current->sref, current->loc);
9058 checkNumerics (ctype tr1, ctype tr2, ctype te1, ctype te2,
9059 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
9064 if (!ctype_match (tr1, tr2))
9066 if ((ctype_isRealInt (tr1) || ctype_isReal (tr1)) &&
9067 (ctype_isRealInt (tr2) || ctype_isReal (tr2)))
9075 message ("Incompatible types for %s (%s, %s): %s %s %s",
9077 ctype_unparse (te1),
9078 ctype_unparse (te2),
9079 exprNode_unparse (e1), lltok_unparse (op),
9080 exprNode_unparse (e2)),
9083 ret = ctype_unknown;
9087 if (ctype_isForceRealNumeric (&tr1) && ctype_isForceRealNumeric (&tr2))
9089 ret = ctype_resolveNumerics (tr1, tr2);
9091 else if (!context_msgStrictOps ())
9093 if (ctype_isPointer (tr1))
9095 if (ctype_isPointer (tr2) && !exprNode_isNullValue (e2))
9099 else if (ctype_isInt (tr2))
9105 ret = ctype_unknown;
9108 else if (ctype_isPointer (tr2))
9110 if (ctype_isPointer (tr1))
9114 else if (ctype_isInt (tr1))
9120 ret = ctype_unknown;
9125 ret = ctype_resolveNumerics (tr1, tr2);
9130 int opid = lltok_getTok (op);
9131 bool comparop = (opid == EQ_OP || opid == NE_OP
9132 || opid == TLT || opid == TGT
9133 || opid == LE_OP || opid == GE_OP);
9135 if (!ctype_isNumeric (tr1) && !ctype_isNumeric (tr2))
9138 && ((ctype_isEnum (tr1) && ctype_isEnum (tr2))
9139 || (ctype_isBool (tr1) && ctype_isBool (tr2))
9140 || (ctype_isChar (tr1) && ctype_isChar (tr2))))
9146 if (ctype_sameName (te1, te2))
9150 message ("Operands of %s are non-numeric (%t): %s %s %s",
9151 lltok_unparse (op), te1,
9152 exprNode_unparse (e1), lltok_unparse (op),
9153 exprNode_unparse (e2)),
9160 message ("Operands of %s are non-numerics (%t, %t): %s %s %s",
9161 lltok_unparse (op), te1, te2,
9162 exprNode_unparse (e1), lltok_unparse (op),
9163 exprNode_unparse (e2)),
9168 else if (!ctype_isNumeric (tr1))
9172 message ("Right operand of %s is non-numeric (%t): %s %s %s",
9173 lltok_unparse (op), te1,
9174 exprNode_unparse (e1), lltok_unparse (op),
9175 exprNode_unparse (e2)),
9180 if (!ctype_isNumeric (tr2))
9184 message ("Left operand of %s is non-numeric (%t): %s %s %s",
9185 lltok_unparse (op), te2,
9186 exprNode_unparse (e1), lltok_unparse (op),
9187 exprNode_unparse (e2)),
9192 ret = ctype_unknown;
9200 abstractOpError (ctype tr1, ctype tr2, lltok op,
9201 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
9202 fileloc loc1, fileloc loc2)
9204 if (ctype_isRealAbstract (tr1) && ctype_isRealAbstract (tr2))
9206 if (ctype_match (tr1, tr2))
9210 message ("Operands of %s are abstract type (%t): %s %s %s",
9211 lltok_unparse (op), tr1,
9212 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
9219 message ("Operands of %s are abstract types (%t, %t): %s %s %s",
9220 lltok_unparse (op), tr1, tr2,
9221 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
9225 else if (ctype_isRealAbstract (tr1))
9229 message ("Left operand of %s is abstract type (%t): %s %s %s",
9230 lltok_unparse (op), tr1,
9231 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
9236 if (ctype_isRealAbstract (tr2))
9240 message ("Right operand of %s is abstract type (%t): %s %s %s",
9241 lltok_unparse (op), tr2,
9242 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
9251 ** requies e1 and e2 and not error exprNode's.
9255 ** If e1 is a component of an abstract type, and e2 is mutable and client-visible,
9256 ** the rep of the abstract type is exposed.
9258 ** The order is very important:
9260 ** check rep expose (move into check transfer)
9266 ** This isn't really a sensible procedure, but the indententation
9267 ** was getting too deep.
9271 checkOneRepExpose (sRef ysr, sRef base,
9272 /*@notnull@*/ exprNode e1,
9273 /*@notnull@*/ exprNode e2, ctype ct,
9276 if (!(sRef_isOnly (ysr) || sRef_isKeep (ysr)
9277 || sRef_isOwned (ysr) || sRef_isExposed (ysr)))
9279 if (sRef_isAnyParam (base) && !sRef_isExposed (base))
9281 if (sRef_isIReference (ysr))
9283 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
9288 ("Assignment of mutable component of parameter %q "
9289 "to component of abstract "
9290 "type %s exposes rep: %s = %s",
9291 sRef_unparse (base),
9293 exprNode_unparse (e1), exprNode_unparse (e2)),
9301 ("Assignment of mutable component of parameter %q "
9302 "(through alias %q) to component of abstract "
9303 "type %s exposes rep: %s = %s",
9304 sRef_unparse (base),
9305 sRef_unparse (e2->sref),
9307 exprNode_unparse (e1), exprNode_unparse (e2)),
9313 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
9317 message ("Assignment of mutable parameter %q "
9318 "to component of abstract type %s "
9319 "exposes rep: %s = %s",
9320 sRef_unparse (base),
9322 exprNode_unparse (e1),
9323 exprNode_unparse (e2)),
9330 message ("Assignment of mutable parameter %q "
9331 "(through alias %q) to "
9332 "component of abstract type %s exposes "
9334 sRef_unparse (base),
9335 sRef_unparse (e2->sref),
9337 exprNode_unparse (e1),
9338 exprNode_unparse (e2)),
9344 if (sRef_isGlobal (s2b))
9346 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
9350 message ("Assignment of global %q "
9352 "abstract type %s exposes rep: %s = %s",
9353 sRef_unparse (base),
9355 exprNode_unparse (e1), exprNode_unparse (e2)),
9362 message ("Assignment of global %q (through alias %q) "
9364 "abstract type %s exposes rep: %s = %s",
9365 sRef_unparse (base),
9366 sRef_unparse (e2->sref),
9368 exprNode_unparse (e1), exprNode_unparse (e2)),
9376 doAssign (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, bool isInit)
9378 if (ctype_isRealFunction (exprNode_getType (e1))
9379 && !ctype_isRealPointer (exprNode_getType (e1)))
9383 message ("Invalid left-hand side of assignment (function type %s): %s",
9384 ctype_unparse (exprNode_getType (e1)),
9385 exprNode_unparse (e1)),
9389 if (context_getFlag (FLG_ASSIGNEXPOSE) && ctype_isMutable (e2->typ))
9391 ctype t2 = exprNode_getType (e2);
9392 sRef sr = sRef_getRootBase (e1->sref);
9393 ctype ct = sRef_getType (sr);
9395 if (ctype_isAbstract (t2)
9396 && !(uentry_isMutableDatatype (usymtab_getTypeEntry (ctype_typeId (t2)))))
9398 /* it is immutable, okay to reference */
9402 if (ctype_isAbstract (ct) && sRef_isIReference (e1->sref))
9404 sRef s2b = sRef_getRootBase (e2->sref);
9406 sRef s1b = sRef_getRootBase (s1);
9409 aliases = usymtab_canAlias (e2->sref);
9411 if (!sRef_similar (s2b, s1b)
9412 && !sRef_isExposed (s1)
9413 && !(sRef_isOnly (s2b) || sRef_isKeep (s2b) || sRef_isExposed (s2b)))
9415 if (sRef_isAnyParam (s2b) && !sRef_isOnly (s2b)
9416 && !sRef_isOwned (s2b) && !sRef_isKeep (s2b)
9417 && !sRef_isExposed (s2b))
9419 if (sRef_isIReference (e2->sref))
9424 ("Assignment of mutable component of parameter %q "
9425 "to component of abstract type %s exposes rep: %s = %s",
9428 exprNode_unparse (e1), exprNode_unparse (e2)),
9435 message ("Assignment of mutable parameter %q to "
9436 "component of abstract type %s exposes rep: %s = %s",
9439 exprNode_unparse (e1), exprNode_unparse (e2)),
9444 if (sRef_isGlobal (s2b))
9448 message ("Assignment of global %q to component of "
9449 "abstract type %s exposes rep: %s = %s",
9452 exprNode_unparse (e1), exprNode_unparse (e2)),
9456 sRefSet_realElements (aliases, ysr)
9458 sRef base = sRef_getRootBase (ysr);
9460 if (sRef_similar (ysr, s2b) || sRef_similar (s1b, base)
9461 || sRef_sameName (base, s1b))
9463 ; /* error already reported or same sref */
9467 checkOneRepExpose (ysr, base, e1, e2, ct, s2b);
9469 } end_sRefSet_realElements;
9471 sRefSet_free (aliases);
9478 ** function variables don't really work...
9481 if (!ctype_isFunction (ctype_realType (e2->typ)))
9485 checkInitTransfer (e1, e2);
9489 checkAssignTransfer (e1, e2);
9494 sRef fref = e2->sref;
9496 sRef_setDefState (e1->sref, sRef_getDefState (fref), e1->loc);
9497 sRef_setNullState (e1->sref, sRef_getNullState (fref), e1->loc);
9499 /* Need to typecheck the annotation on the parameters */
9501 if (ctype_isRealFunction (e1->typ)) {
9502 uentryList e1p = ctype_argsFunction (ctype_realType (e1->typ));
9503 uentryList e2p = ctype_argsFunction (ctype_realType (e2->typ));
9505 if (!uentryList_isMissingParams (e1p)
9506 && !uentryList_isMissingParams (e2p)
9507 && uentryList_size (e1p) > 0) {
9508 if (uentryList_size (e1p) == uentryList_size (e2p)) {
9511 uentryList_elements (e1p, el1) {
9514 el2 = uentryList_getN (e2p, n);
9516 uentry_checkMatchParam (el1, el2, n, e2);
9517 } end_uentryList_elements;
9523 if (isInit && sRef_isGlobal (e1->sref))
9529 updateAliases (e1, e2);
9534 checkMacroParen (exprNode e)
9536 if (exprNode_isError (e) || e->kind == XPR_CAST)
9542 if (sRef_isUnsafe (e->sref) && !exprNode_isInParens (e))
9546 message ("Macro parameter used without parentheses: %s",
9547 exprNode_unparse (e)),
9554 reflectNullTest (/*@notnull@*/ exprNode e, bool isnull)
9558 e->guards = guardSet_addTrueGuard (e->guards, e->sref);
9562 e->guards = guardSet_addFalseGuard (e->guards, e->sref);
9569 ** if e2 is a parameter or global derived location which
9570 ** can be modified (that is, e2 is a mutable abstract type,
9571 ** or a derived pointer), then e1 can alias e2.
9573 ** e1 can alias everything which e2 can alias.
9575 ** Also, if e1 is guarded, remove from guard sets!
9578 static void updateAliases (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2)
9580 if (!context_inProtectVars ())
9583 ** depends on types of e1 and e2
9588 ctype t1 = exprNode_getType (e1);
9590 /* handle pointer sRefs, record fields, arrays, etc... */
9592 if (!ctype_isRealSU (t1))
9594 sRef_copyRealDerivedComplete (s1, s2);
9597 if (ctype_isMutable (t1) && sRef_isKnown (s1))
9599 usymtab_clearAlias (s1);
9600 usymtab_addMustAlias (s1, s2);
9603 if (sRef_possiblyNull (s1) && usymtab_isGuarded (s1))
9605 usymtab_unguard (s1);
9610 exprNode exprNode_updateLocation (/*@returned@*/ exprNode e, /*@temp@*/ fileloc loc)
9612 if (exprNode_isDefined (e))
9614 e->loc = fileloc_update (e->loc, loc);
9618 e = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
9624 static void checkUniqueParams (exprNode fcn,
9625 /*@notnull@*/ exprNode current,
9627 int paramno, uentry ucurrent)
9630 sRef thisref = exprNode_getSref (current);
9633 ** Check if any argument could match this argument.
9636 exprNodeList_elements (args, icurrent)
9640 if (iparamno != paramno)
9642 sRef sr = exprNode_getSref (icurrent);
9644 if (sRef_similarRelaxed (thisref, sr))
9646 if (!sRef_isConst (thisref) && !sRef_isConst (sr))
9651 ("Parameter %d (%s) to function %s is declared %s but "
9652 "is aliased by parameter %d (%s)",
9654 exprNode_unparse (current),
9655 exprNode_unparse (fcn),
9656 alkind_unparse (uentry_getAliasKind (ucurrent)),
9657 iparamno, exprNode_unparse (icurrent)),
9663 sRefSet aliases = usymtab_canAlias (sr);
9665 sRefSet_allElements (aliases, asr)
9667 if (ctype_isUnknown (sRef_getType (thisref)))
9669 sRef_setType (thisref, uentry_getType (ucurrent));
9672 if (sRef_similarRelaxed (thisref, asr))
9674 if (sRef_isExternal (asr))
9676 if (sRef_isLocalState (thisref))
9682 sRef base = sRef_getRootBase (asr);
9684 if (!sRef_similar (sRef_getBase (asr), thisref))
9686 if (sRef_isUnique (base) || sRef_isOnly (base)
9687 || sRef_isKept (base)
9688 || (sRef_isAddress (asr) && sRef_isLocalVar (base))
9689 || (sRef_isAddress (thisref)
9690 && sRef_isLocalVar (sRef_getRootBase (thisref))))
9692 ; /* okay, no error */
9697 (FLG_MAYALIASUNIQUE,
9699 ("Parameter %d (%s) to function %s is declared %s but "
9700 "may be aliased externally by parameter %d (%s)",
9702 exprNode_unparse (current),
9703 exprNode_unparse (fcn),
9704 alkind_unparse (uentry_getAliasKind (ucurrent)),
9705 iparamno, exprNode_unparse (icurrent)),
9716 ("Parameter %d (%s) to function %s is declared %s but "
9717 "is aliased externally by parameter %d (%s) through "
9720 exprNode_unparse (current),
9721 exprNode_unparse (fcn),
9722 alkind_unparse (uentry_getAliasKind (ucurrent)),
9723 iparamno, exprNode_unparse (icurrent),
9724 sRef_unparse (asr)),
9728 } end_sRefSet_allElements;
9729 sRefSet_free (aliases);
9732 } end_exprNodeList_elements;