2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 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 splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
28 # include "splintMacros.nf"
31 # include "cscannerHelp.h"
32 # include "cgrammar.h"
34 # include "exprChecks.h"
35 # include "transferChecks.h"
36 # include "exprNodeSList.h"
38 static bool exprNode_sameStorage (exprNode p_e1
, exprNode p_e2
) /*@*/ ;
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_isStatement (exprNode p_e
);
43 static /*@falsewhennull@*/ bool exprNode_isBlock (exprNode p_e
) /*@*/ ;
44 static void checkGlobUse (uentry p_glob
, bool p_isCall
, /*@notnull@*/ exprNode p_e
);
45 static void exprNode_addUse (exprNode p_e
, /*@exposed@*/ sRef p_s
);
46 static bool exprNode_matchArgType (ctype p_ct
, exprNode p_e
);
47 static exprNode
exprNode_fakeCopy (exprNode p_e
) /*@*/ ;
48 static exprNode
exprNode_statementError (/*@only@*/ exprNode p_e
, /*@only@*/ lltok p_t
);
49 static bool exprNode_matchTypes (exprNode p_e1
, exprNode p_e2
);
50 static void checkUniqueParams (exprNode p_fcn
,
51 /*@notnull@*/ exprNode p_current
, exprNodeList p_args
,
52 int p_paramno
, uentry p_ucurrent
);
53 static void updateAliases (/*@notnull@*/ exprNode p_e1
, /*@notnull@*/ exprNode p_e2
);
54 static bool abstractOpError (ctype p_tr1
, ctype p_tr2
, lltok p_op
,
55 /*@notnull@*/ exprNode p_e1
, /*@notnull@*/ exprNode p_e2
,
56 fileloc p_loc1
, fileloc p_loc2
)
57 /*@modifies g_warningstream@*/ ;
58 static ctype
checkNumerics (ctype p_tr1
, ctype p_tr2
, ctype p_te1
, ctype p_te2
,
59 /*@notnull@*/ exprNode p_e1
, /*@notnull@*/ exprNode p_e2
, lltok p_op
);
60 static void doAssign (/*@notnull@*/ exprNode p_e1
, /*@notnull@*/ exprNode p_e2
, bool p_isInit
);
61 static void checkSafeUse (exprNode p_e
, /*@exposed@*/ sRef p_s
);
62 static void reflectNullTest (/*@notnull@*/ exprNode p_e
, bool p_isnull
);
63 static void checkMacroParen (exprNode p_e
);
64 static exprNodeSList
exprNode_flatten (/*@dependent@*/ exprNode p_e
);
65 static void exprNode_checkSetAny (exprNode p_e
, /*@dependent@*/ cstring p_name
);
66 static void exprNode_checkUse (exprNode p_e
, /*@exposed@*/ sRef p_s
, fileloc p_loc
);
67 static void exprNode_mergeUSs (exprNode p_res
, exprNode p_other
);
68 static void exprNode_mergeCondUSs (exprNode p_res
, exprNode p_other1
, exprNode p_other2
);
69 static /*@only@*/ /*@notnull@*/ exprNode
exprNode_fromIdentifierAux (/*@observer@*/ uentry p_c
);
70 static void checkAnyCall (/*@notnull@*/ /*@dependent@*/ exprNode p_fcn
,
71 /*@dependent@*/ cstring p_fname
,
72 uentryList p_pn
, exprNodeList p_args
,
73 bool p_hasMods
, sRefSet p_mods
, bool p_isSpec
,
75 static void checkOneArg (uentry p_ucurrent
, /*@notnull@*/ exprNode p_current
,
76 /*@dependent@*/ exprNode p_fcn
, bool p_isSpec
, int p_argno
, int p_totargs
);
78 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode p_fcn
, uentryList p_params
, exprNodeList p_args
);
80 static /*@only@*/ exprNode
exprNode_effect (exprNode p_e
)
81 /*@globals internalState@*/ ;
82 static /*@only@*/ cstring
exprNode_doUnparse (exprNode p_e
);
83 static /*@observer@*/ cstring
exprNode_rootVarName (exprNode p_e
);
84 static /*@exposed@*/ exprNode
85 exprNode_lastStatement (/*@returned@*/ exprNode p_e
);
87 static /*@only@*/ exprNode s_mustExitNode
= exprNode_undefined
;
89 static int checkArgsReal (uentry p_fcn
, /*@dependent@*/ exprNode p_f
,
91 exprNodeList p_args
, bool p_isIter
, exprNode p_ret
);
93 static bool inEffect
= FALSE
;
94 static int nowalloc
= 0;
95 static int totalloc
= 0;
96 static int maxalloc
= 0;
98 static /*@only@*/ uentry regArg
;
99 static /*@only@*/ uentry outArg
;
100 static /*@only@*/ uentry outStringArg
;
101 static /*@exposed@*/ sRef stdinRef
;
102 static /*@exposed@*/ sRef stdoutRef
;
103 static /*@only@*/ uentry csArg
;
104 static /*@only@*/ uentry csOnlyArg
;
105 static ctype cstringType
;
106 static ctype ctypeType
;
107 static ctype filelocType
;
108 static bool initMod
= FALSE
;
110 /*@function void exprNode_swap (sef exprNode, sef exprNode)@*/
112 # define exprNode_swap(e1,e2) do { exprNode m_tmp = (e1); (e1) = (e2); (e2) = m_tmp; } while (FALSE)
115 static void exprNode_defineConstraints(/*@sef@*/ /*@special@*/ /*@notnull@*/ exprNode e
)
116 /*@defines e->requiresConstraints, e->ensuresConstraints,
117 e->trueEnsuresConstraints, e->falseEnsuresConstraints @*/
119 e
->requiresConstraints
= constraintList_makeNew ();
120 e
->ensuresConstraints
= constraintList_makeNew ();
121 e
->trueEnsuresConstraints
= constraintList_makeNew ();
122 e
->falseEnsuresConstraints
= constraintList_makeNew ();
126 ** must occur after library has been read
129 void exprNode_initMod (void)
130 /*@globals undef regArg, undef outArg, undef outStringArg,
131 undef csOnlyArg, undef csArg;
138 cstringType
= ctype_unknown
;
139 ctypeType
= ctype_unknown
;
140 filelocType
= ctype_unknown
;
142 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
144 cstringType
= usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
147 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
149 ctypeType
= usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
152 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
154 filelocType
= usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
157 if (usymtab_existsGlob (cstring_makeLiteralTemp ("stdin")))
159 ue
= usymtab_lookupGlob (cstring_makeLiteralTemp ("stdin"));
161 else /* define stdin */
163 ue
= uentry_makeVariable (cstring_makeLiteralTemp ("stdin"),
165 fileloc_getBuiltin (),
167 uentry_setHasNameError (ue
);
168 ue
= usymtab_supGlobalEntryReturn (ue
);
171 stdinRef
= sRef_makePointer (uentry_getSref (ue
));
173 if (usymtab_existsGlob (cstring_makeLiteralTemp ("stdout")))
175 ue
= usymtab_lookupGlob (cstring_makeLiteralTemp ("stdout"));
179 ue
= uentry_makeVariable (cstring_makeLiteralTemp ("stdout"),
181 fileloc_getBuiltin (),
183 uentry_setHasNameError (ue
);
184 ue
= usymtab_supGlobalEntryReturn (ue
);
187 stdoutRef
= sRef_makePointer (uentry_getSref (ue
));
189 tmp
= idDecl_create (cstring_undefined
, qtype_create (ctype_unknown
));
191 regArg
= uentry_makeParam (tmp
, PARAMUNKNOWN
);
194 qtype_addQual (qtype_create (ctype_makePointer (ctype_unknown
)),
197 outArg
= uentry_makeParam (tmp
, PARAMUNKNOWN
);
199 idDecl_setTyp (tmp
, qtype_addQual (qtype_create (ctype_string
),
202 outStringArg
= uentry_makeParam (tmp
, PARAMUNKNOWN
);
204 idDecl_setTyp (tmp
, qtype_addQual (qtype_addQual (qtype_create (cstringType
),
206 qual_createNull ()));
208 csOnlyArg
= uentry_makeParam (tmp
, PARAMUNKNOWN
);
210 idDecl_setTyp (tmp
, qtype_addQual (qtype_create (cstringType
), qual_createNull ()));
211 csArg
= uentry_makeParam (tmp
, PARAMUNKNOWN
);
217 exprNode_destroyMod (void)
218 /*@globals killed regArg, killed outArg, killed outStringArg,
219 killed s_mustExitNode, initMod @*/
223 /* evans 2002-07-12: changed uentry_free to uentry_freeComplete */
224 uentry_freeComplete (regArg
);
225 uentry_freeComplete (outArg
);
226 uentry_freeComplete (outStringArg
);
228 exprNode_free (s_mustExitNode
);
235 static void exprNode_resetSref (/*@notnull@*/ exprNode e
)
237 e
->sref
= sRef_undefined
;
240 exprNode
exprNode_fakeCopy (exprNode e
)
242 /*@-temptrans@*/ /*@-retalias@*/
244 /*@=temptrans@*/ /*@=retalias@*/
247 static bool isFlagKey (char key
)
249 return (key
== '-' || key
== '+' || key
== ' ' || key
== '#');
252 static void exprNode_combineControl (/*@notnull@*/ exprNode ret
,
253 /*@notnull@*/ exprNode ifclause
,
254 /*@notnull@*/ exprNode elseclause
)
256 ret
->canBreak
= ifclause
->canBreak
|| elseclause
->canBreak
;
259 (ifclause
->mustBreak
|| exprNode_mustEscape (ifclause
))
260 && (elseclause
->mustBreak
|| exprNode_mustEscape (elseclause
));
262 ret
->exitCode
= exitkind_combine (ifclause
->exitCode
,
263 elseclause
->exitCode
);
268 ** For exprNode's returned by exprNode_effect.
271 static bool shallowKind (exprKind kind
)
273 return (kind
== XPR_STRINGLITERAL
274 || kind
== XPR_NUMLIT
277 || kind
== XPR_NODE
);
281 exprNode_freeIniter (/*@only@*/ exprNode e
)
283 if (!exprNode_isError (e
))
289 ** Its a fake copy, don't free the field->rec and field->field
294 sfree (e
->edata
->field
);
300 exprNode_free (e
->edata
->op
->b
);
301 /*@-compdestroy@*/ sfree (e
->edata
->op
); /*@=compdestroy@*/
305 llbug (message ("other: %s", exprNode_unparse (e
)));
308 multiVal_free (e
->val
);
309 cstring_free (e
->etext
);
310 fileloc_free (e
->loc
);
311 sRefSet_free (e
->uses
);
312 sRefSet_free (e
->sets
);
313 sRefSet_free (e
->msets
);
314 guardSet_free (e
->guards
);
316 constraintList_free(e
->requiresConstraints
);
317 constraintList_free(e
->ensuresConstraints
);
318 constraintList_free(e
->trueEnsuresConstraints
);
319 constraintList_free(e
->falseEnsuresConstraints
);
321 e
->requiresConstraints
= NULL
;
322 e
->ensuresConstraints
= NULL
;
323 e
->trueEnsuresConstraints
= NULL
;
324 e
->falseEnsuresConstraints
= NULL
;
331 exprNode_freeShallow (/*@only@*/ exprNode e
)
333 if (!exprNode_isError (e
))
335 if (shallowKind (e
->kind
))
342 if (e
->kind
== XPR_EMPTY
343 || e
->kind
== XPR_BODY
344 || e
->kind
== XPR_STRINGLITERAL
345 || e
->kind
== XPR_NUMLIT
346 || e
->kind
== XPR_NODE
347 || e
->kind
== XPR_OFFSETOF
348 || e
->kind
== XPR_ALIGNOFT
349 || e
->kind
== XPR_ALIGNOF
350 || e
->kind
== XPR_SIZEOFT
351 || e
->kind
== XPR_SIZEOF
)
353 /* don't free anything */
357 /* multiVal_free (e->val); */
358 cstring_free (e
->etext
);
359 fileloc_free (e
->loc
);
360 sRefSet_free (e
->uses
);
361 sRefSet_free (e
->sets
);
362 sRefSet_free (e
->msets
);
363 guardSet_free (e
->guards
);
364 exprData_freeShallow (e
->edata
, e
->kind
);
366 /*@-compdestroy@*/ sfree (e
); /*@=compdestroy@*/
375 exprNode_free (exprNode e
)
377 if (!exprNode_isError (e
))
381 multiVal_free (e
->val
);
382 cstring_free (e
->etext
);
383 fileloc_free (e
->loc
);
384 sRefSet_free (e
->uses
);
385 sRefSet_free (e
->sets
);
386 sRefSet_free (e
->msets
);
387 guardSet_free (e
->guards
);
388 exprData_free (e
->edata
, e
->kind
);
390 constraintList_free(e
->requiresConstraints
);
391 constraintList_free(e
->ensuresConstraints
);
392 constraintList_free(e
->trueEnsuresConstraints
);
393 constraintList_free(e
->falseEnsuresConstraints
);
395 e
->requiresConstraints
= NULL
;
396 e
->ensuresConstraints
= NULL
;
397 e
->trueEnsuresConstraints
= NULL
;
398 e
->falseEnsuresConstraints
= NULL
;
408 exprNode_makeError (void)
410 return exprNode_undefined
;
413 static /*@out@*/ /*@only@*/ /*@notnull@*/ exprNode
416 exprNode ret
= (exprNode
) dmalloc (sizeof (*ret
));
417 /* static int lastexpnodes = 0; */
422 if (nowalloc
> maxalloc
)
430 static /*@notnull@*/ /*@special@*/ exprNode
431 exprNode_createPlain (ctype c
)
433 /*@ensures isnull result->edata, result->loc, result->val, result->guards,
434 result->uses, result->sets, result->msets, result->etext @*/
437 exprNode e
= exprNode_new ();
441 e
->val
= multiVal_undefined
;
442 e
->sref
= sRef_undefined
;
443 e
->etext
= cstring_undefined
;
444 e
->loc
= fileloc_undefined
;
445 e
->guards
= guardSet_undefined
;
446 e
->uses
= sRefSet_undefined
;
447 e
->sets
= sRefSet_undefined
;
448 e
->msets
= sRefSet_undefined
;
449 e
->edata
= exprData_undefined
;
450 e
->exitCode
= XK_NEVERESCAPE
;
452 e
->mustBreak
= FALSE
;
453 e
->isJumpPoint
= FALSE
;
455 exprNode_defineConstraints(e
);
460 /*@observer@*/ exprNode
exprNode_makeMustExit (void)
462 if (exprNode_isUndefined (s_mustExitNode
))
464 s_mustExitNode
= exprNode_createPlain (ctype_unknown
);
465 s_mustExitNode
->exitCode
= XK_MUSTEXIT
;
468 return s_mustExitNode
;
472 static /*@notnull@*/ /*@special@*/ exprNode
exprNode_create (ctype c
)
474 /*@post:isnull result->edata, result->guards, result->val,
475 result->uses, result->sets, result->msets@*/
478 exprNode e
= exprNode_createPlain (c
);
479 e
->loc
= fileloc_copy (g_currentloc
);
483 static /*@notnull@*/ /*@special@*/ exprNode
exprNode_createUnknown (void)
485 /*@post:isnull result->edata, result->guards,
486 result->uses, result->sets, result->msets@*/
489 return (exprNode_create (ctype_unknown
));
492 static /*@notnull@*/ /*@special@*/ exprNode
493 exprNode_createLoc (ctype c
, /*@keep@*/ fileloc loc
)
495 /*@post:isnull result->edata, result->guards, result->val,
496 result->uses, result->sets, result->msets@*/
499 exprNode e
= exprNode_createPlain (c
);
505 exprNode_copySets (/*@special@*/ /*@notnull@*/ exprNode ret
, exprNode e
)
506 /*@defines ret->guards, ret->uses, ret->sets, ret->msets@*/
508 if (exprNode_isDefined (e
))
510 ret
->guards
= guardSet_copy (e
->guards
);
511 ret
->uses
= sRefSet_newCopy (e
->uses
);
512 ret
->sets
= sRefSet_newCopy (e
->sets
);
513 ret
->msets
= sRefSet_newCopy (e
->msets
);
517 ret
->guards
= guardSet_undefined
;
518 ret
->uses
= sRefSet_undefined
;
519 ret
->sets
= sRefSet_undefined
;
520 ret
->msets
= sRefSet_undefined
;
524 static /*@notnull@*/ /*@special@*/ exprNode
525 exprNode_createPartialLocCopy (exprNode e
, /*@only@*/ fileloc loc
)
527 /*@post:isnull result->edata, result->etext@*/
530 exprNode ret
= exprNode_new ();
532 if (exprNode_isError (e
))
534 ret
->typ
= ctype_unknown
;
535 ret
->val
= multiVal_undefined
;
537 ret
->guards
= guardSet_undefined
;
538 ret
->uses
= sRefSet_undefined
;
539 ret
->sets
= sRefSet_undefined
;
540 ret
->msets
= sRefSet_undefined
;
545 ret
->val
= multiVal_copy (e
->val
);
547 ret
->guards
= guardSet_copy (e
->guards
);
548 ret
->uses
= sRefSet_newCopy (e
->uses
);
549 ret
->sets
= sRefSet_newCopy (e
->sets
);
550 ret
->msets
= sRefSet_newCopy (e
->msets
);
553 ret
->kind
= XPR_EMPTY
;
554 ret
->sref
= sRef_undefined
;
555 ret
->etext
= cstring_undefined
;
556 ret
->exitCode
= XK_NEVERESCAPE
;
557 ret
->canBreak
= FALSE
;
558 ret
->mustBreak
= FALSE
;
559 ret
->isJumpPoint
= FALSE
;
560 ret
->edata
= exprData_undefined
;
562 exprNode_defineConstraints(ret
);
568 static /*@notnull@*/ /*@special@*/ exprNode
569 exprNode_createPartialCopy (exprNode e
)
571 /*@post:isnull result->edata, result->etext@*/
574 return (exprNode_createPartialLocCopy (e
, fileloc_copy (exprNode_loc (e
))));
577 static /*@notnull@*/ /*@special@*/ exprNode
578 exprNode_createPartialNVCopy (exprNode e
)
580 /*@post:isnull result->edata, result->etext, result->val @*/
583 exprNode ret
= exprNode_new ();
585 if (exprNode_isError (e
))
587 ret
->typ
= ctype_unknown
;
588 ret
->loc
= fileloc_undefined
;
589 ret
->guards
= guardSet_undefined
;
590 ret
->uses
= sRefSet_undefined
;
591 ret
->sets
= sRefSet_undefined
;
592 ret
->msets
= sRefSet_undefined
;
597 ret
->loc
= fileloc_copy (e
->loc
);
598 ret
->guards
= guardSet_copy (e
->guards
);
599 ret
->uses
= sRefSet_newCopy (e
->uses
);
600 ret
->sets
= sRefSet_newCopy (e
->sets
);
601 ret
->msets
= sRefSet_newCopy (e
->msets
);
604 ret
->val
= multiVal_undefined
;
605 ret
->kind
= XPR_EMPTY
;
606 ret
->sref
= sRef_undefined
;
607 ret
->etext
= cstring_undefined
;
608 ret
->exitCode
= XK_NEVERESCAPE
;
609 ret
->canBreak
= FALSE
;
610 ret
->mustBreak
= FALSE
;
611 ret
->isJumpPoint
= FALSE
;
612 ret
->edata
= exprData_undefined
;
614 exprNode_defineConstraints(ret
);
619 static /*@notnull@*/ /*@special@*/ exprNode
620 exprNode_createSemiCopy (exprNode e
)
622 /*@post:isnull result->edata, result->etext, result->sets,
623 result->msets, result->uses, result->guards@*/
626 if (exprNode_isError (e
))
628 return exprNode_createPlain (ctype_unknown
);
632 exprNode ret
= exprNode_new ();
635 ret
->val
= multiVal_copy (e
->val
);
636 ret
->loc
= fileloc_copy (e
->loc
);
637 ret
->guards
= guardSet_undefined
;
638 ret
->uses
= sRefSet_undefined
;
639 ret
->sets
= sRefSet_undefined
;
640 ret
->msets
= sRefSet_undefined
;
642 ret
->kind
= XPR_EMPTY
;
643 ret
->sref
= sRef_undefined
;
644 ret
->etext
= cstring_undefined
;
645 ret
->exitCode
= XK_NEVERESCAPE
;
646 ret
->canBreak
= FALSE
;
647 ret
->mustBreak
= FALSE
;
648 ret
->isJumpPoint
= FALSE
;
649 ret
->edata
= exprData_undefined
;
651 exprNode_defineConstraints(ret
);
658 exprNode_isNullValue (exprNode e
)
660 if (exprNode_isDefined (e
))
662 multiVal m
= exprNode_getValue (e
);
664 if (multiVal_isInt (m
))
666 return (multiVal_forceInt (m
) == 0);
674 exprNode_isUnknownConstant (/*@notnull@*/ exprNode e
)
676 while (e
->kind
== XPR_PARENS
)
678 e
= exprData_getUopNode (e
->edata
);
680 if (!exprNode_isDefined (e
))
685 /* evans 2002-02-05: was llassert (exprNode_isDefined (e)); but this can fail */
688 if (e
->kind
== XPR_CONST
)
690 multiVal m
= exprNode_getValue (e
);
692 if (multiVal_isUnknown (m
))
702 exprNode_numLiteral (ctype c
, /*@temp@*/ cstring t
,
703 /*@only@*/ fileloc loc
, long val
)
705 exprNode e
= exprNode_createLoc (c
, loc
);
707 e
->kind
= XPR_NUMLIT
;
709 llassert (multiVal_isUndefined (e
->val
));
710 e
->val
= multiVal_makeInt (val
);
711 e
->edata
= exprData_makeLiteral (cstring_copy (t
));
715 e
->sref
= sRef_makeUnknown ();
716 sRef_setDefNull (e
->sref
, e
->loc
);
719 DPRINTF (("Num lit: %s / %s", exprNode_unparse (e
), ctype_unparse (exprNode_getType (e
))));
724 exprNode_charLiteral (char c
, cstring text
, /*@only@*/ fileloc loc
)
726 exprNode e
= exprNode_createLoc (ctype_char
, loc
);
728 if (context_getFlag (FLG_CHARINTLITERAL
))
730 e
->typ
= ctype_makeConj (ctype_char
, ctype_int
);
733 e
->kind
= XPR_NUMLIT
;
734 e
->val
= multiVal_makeChar (c
);
736 e
->edata
= exprData_makeLiteral (cstring_copy (text
));
741 exprNode_floatLiteral (double d
, ctype ct
, cstring text
, /*@only@*/ fileloc loc
)
743 exprNode e
= exprNode_createLoc (ct
, loc
);
745 e
->kind
= XPR_NUMLIT
;
746 e
->val
= multiVal_makeDouble (d
);
747 e
->edata
= exprData_makeLiteral (cstring_copy (text
));
751 multiVal
exprNode_getValue (exprNode e
)
753 while (exprNode_isInParens (e
)) {
754 if (e
->edata
!= NULL
) {
755 e
= exprData_getUopNode (e
->edata
);
761 if (exprNode_isDefined (e
)) {
764 return multiVal_undefined
;
769 exprNode_combineLiterals (exprNode e
, exprNode rest
)
773 /* Both must be string literals. */
775 if (exprNode_isUndefined (rest
) || exprNode_isUndefined (e
))
777 exprNode_free (rest
);
781 if (!exprNode_isStringLiteral (e
))
785 message ("Constant concatentation is ungrammatical: %s %s", exprNode_unparse (e
),
786 exprNode_unparse (rest
)),
788 exprNode_free (rest
);
792 if (!exprNode_isStringLiteral (rest
))
796 message ("Constant concatentation is ungrammatical: %s %s", exprNode_unparse (e
), exprNode_unparse (rest
)),
799 exprNode_free (rest
);
803 ns
= cstring_concat (multiVal_forceString (exprNode_getValue (e
)),
804 multiVal_forceString (exprNode_getValue (rest
)));
806 multiVal_free (e
->val
);
807 exprData_free (e
->edata
, e
->kind
);
808 e
->edata
= exprData_makeLiteral (cstring_copy (ns
));
809 e
->val
= multiVal_makeString (ns
);
810 exprNode_free (rest
);
814 static /*@notnull@*/ /*@only@*/ exprNode
815 exprNode_rawStringLiteral (/*@only@*/ cstring t
, /*@only@*/ fileloc loc
)
817 exprNode e
= exprNode_createLoc (ctype_string
, loc
);
818 size_t len
= cstring_length (t
);
820 if (context_getFlag (FLG_STRINGLITERALLEN
))
822 if (len
> size_fromInt (context_getValue (FLG_STRINGLITERALLEN
)))
824 voptgenerror (FLG_STRINGLITERALLEN
,
826 ("String literal length (%d) exceeds maximum "
827 "length (%d): \"%s\"",
829 context_getValue (FLG_STRINGLITERALLEN
),
835 e
->kind
= XPR_STRINGLITERAL
;
836 e
->val
= multiVal_makeString (cstring_copy (t
));
837 e
->edata
= exprData_makeLiteral (t
);
838 e
->sref
= sRef_makeConst (ctype_string
);
840 if (context_getFlag (FLG_READONLYSTRINGS
))
842 sRef_setAliasKind (e
->sref
, AK_STATIC
, fileloc_undefined
);
843 sRef_setExKind (e
->sref
, XO_OBSERVER
, loc
);
847 sRef_setAliasKind (e
->sref
, AK_ERROR
, fileloc_undefined
);
850 return (e
); /* s released */
854 exprNode_wideStringLiteral (/*@only@*/ cstring t
, /*@only@*/ fileloc loc
)
856 exprNode res
= exprNode_stringLiteral (t
, loc
);
857 res
->typ
= ctype_makeWideString ();
862 exprNode_stringLiteral (/*@only@*/ cstring t
, /*@only@*/ fileloc loc
)
864 size_t len
= size_fromInt (size_toInt (cstring_length (t
)) - 2);
865 char *ts
= cstring_toCharsSafe (t
);
866 char *s
= cstring_toCharsSafe (cstring_create (len
+ 1));
868 llassert (*ts
== '\"' && *(ts
+ len
+ 1) == '\"');
869 strncpy (s
, ts
+1, len
);
872 return exprNode_rawStringLiteral (cstring_fromCharsO (s
), loc
);
875 exprNode
exprNode_fromUIO (cstring c
)
877 fileloc loc
= context_getSaveLocation ();
878 exprNode e
= exprNode_createPlain (ctype_unknown
);
882 if (fileloc_isUndefined (loc
))
884 loc
= fileloc_copy (g_currentloc
);
887 e
->loc
= loc
; /* save loc was mangled */
888 e
->sref
= sRef_undefined
;
890 if (usymtab_exists (c
))
892 uentry ue
= usymtab_lookupEither (c
);
894 if (uentry_isDatatype (ue
)
895 && uentry_isSpecified (ue
))
898 (message ("%q: Specified datatype %s used in code, but not defined. "
899 "(Cannot continue reasonably from this error.)",
900 fileloc_unparse (e
->loc
), c
));
908 llassertprint (!usymtab_exists (c
), ("Entry exists: %s", c
));
911 ** was supercedeGlobalEntry...is this better?
914 if (!context_inIterEnd ())
916 if (context_inMacro ())
918 if (context_getFlag (FLG_UNRECOG
))
922 message ("Unrecognized identifier in macro definition: %s", c
), e
->loc
);
926 flagcode_recordSuppressed (FLG_UNRECOG
);
932 (FLG_UNRECOG
, message ("Unrecognized identifier: %s", c
), e
->loc
);
936 e
->edata
= exprData_makeId (uentry_makeUnrecognized (c
, fileloc_copy (loc
)));
938 /* No alias errors for unrecognized identifiers */
939 sRef_setAliasKind (e
->sref
, AK_ERROR
, loc
);
944 exprNode
exprNode_makeConstantString (cstring c
, /*@only@*/ fileloc loc
)
946 exprNode e
= exprNode_createPlain (ctype_unknown
);
949 e
->sref
= sRef_makeConst (ctype_string
);
950 e
->edata
= exprData_makeId (uentry_makeUnrecognized (c
, fileloc_copy (loc
)));
951 e
->typ
= ctype_string
;
953 /* No alias errors for unrecognized identifiers */
954 sRef_setAliasKind (e
->sref
, AK_STATIC
, loc
);
955 sRef_setExKind (e
->sref
, XO_OBSERVER
, loc
);
960 exprNode
exprNode_createId (/*@observer@*/ uentry c
)
962 if (uentry_isValid (c
))
964 exprNode e
= exprNode_new ();
966 DPRINTF (("create id: %s", uentry_unparse (c
)));
968 e
->typ
= uentry_getType (c
);
970 if (uentry_isFunction (c
)
971 && !sRef_isLocalVar (uentry_getSref (c
)))
973 e
->sref
= sRef_undefined
;
977 e
->sref
= uentry_getSref (c
);
980 if (sRef_isStateUnknown (e
->sref
) && uentry_isNonLocal (c
))
982 sRef_setDefined (e
->sref
, fileloc_undefined
);
986 ** yoikes! leaving this out was a heinous bug...that would have been
987 ** caught if i had splint working first. gag!
990 e
->etext
= cstring_undefined
;
992 if (uentry_isEitherConstant (c
))
995 e
->val
= multiVal_copy (uentry_getConstantValue (c
));
1000 e
->val
= multiVal_unknown ();
1003 e
->edata
= exprData_makeId (c
);
1004 e
->loc
= context_getSaveLocation ();
1006 if (fileloc_isUndefined (e
->loc
))
1008 fileloc_free (e
->loc
);
1009 e
->loc
= fileloc_copy (g_currentloc
);
1012 e
->guards
= guardSet_new ();
1014 e
->sets
= sRefSet_new ();
1015 e
->msets
= sRefSet_new ();
1016 e
->uses
= sRefSet_new ();
1018 /*> missing fields, detected by splint <*/
1019 e
->exitCode
= XK_NEVERESCAPE
;
1020 e
->isJumpPoint
= FALSE
;
1021 e
->canBreak
= FALSE
;
1022 e
->mustBreak
= FALSE
;
1024 exprNode_defineConstraints (e
);
1029 return exprNode_createUnknown ();
1033 /*@notnull@*/ exprNode
1034 exprNode_fromIdentifier (/*@observer@*/ uentry c
)
1038 if (context_justPopped ()) /* watch out! c could be dead */
1040 uentry ce
= usymtab_lookupSafe (cscannerHelp_observeLastIdentifier ());
1042 if (uentry_isValid (ce
))
1048 llbuglit ("Looks like Aunt Millie forgot to walk to dog again.");
1052 ret
= exprNode_fromIdentifierAux (c
);
1056 static void exprNode_checkStringLiteralLength (ctype t1
, exprNode e2
)
1058 multiVal mval
= exprNode_getValue (e2
);
1062 if (ctype_isFixedArray (t1
))
1064 size_t nelements
= ctype_getArraySize (t1
);
1066 llassert (multiVal_isString (mval
));
1067 slit
= multiVal_forceString (mval
);
1069 len
= cstring_lengthExpandEscapes (slit
);
1071 llassert (exprNode_isDefined (e2
));
1073 if (len
== nelements
)
1077 temp
= cstring_expandEscapes (slit
);
1079 if (temp
[len
-1] == '\0')
1082 (FLG_STRINGLITNOROOMFINALNULL
,
1083 message ("String literal with %d character%& "
1084 "is assigned to %s (no room for final null terminator): %s",
1085 size_toInt (len
+ 1),
1087 exprNode_unparse (e2
)),
1093 (FLG_STRINGLITNOROOM
,
1094 message ("String literal with %d character%& "
1095 "is assigned to %s (no room for null terminator): %s",
1096 size_toInt (len
+ 1),
1098 exprNode_unparse (e2
)),
1102 else if (len
> nelements
)
1105 (FLG_STRINGLITTOOLONG
,
1106 message ("String literal with %d character%& (counting null terminator) "
1107 "is assigned to %s (insufficient storage available): %s",
1108 size_toInt (len
+ 1),
1110 exprNode_unparse (e2
)),
1113 else if (len
< nelements
- 1)
1116 (FLG_STRINGLITSMALLER
,
1117 message ("String literal with %d character%& is assigned to %s (possible waste of storage): %s",
1118 size_toInt (len
+ 1),
1120 exprNode_unparse (e2
)),
1130 static /*@only@*/ /*@notnull@*/ exprNode
1131 exprNode_fromIdentifierAux (/*@observer@*/ uentry c
)
1133 exprNode e
= exprNode_createId (c
);
1136 uentry_setUsed (c
, e
->loc
);
1138 if (uentry_isVar (c
) && sRef_isFileOrGlobalScope (sr
))
1140 checkGlobUse (c
, FALSE
, e
);
1147 exprNode_isZero (exprNode e
)
1149 if (exprNode_isDefined (e
))
1151 multiVal m
= exprNode_getValue (e
);
1153 if (multiVal_isInt (m
))
1155 return (multiVal_forceInt (m
) == 0);
1163 exprNode_isNonNegative (exprNode e
)
1165 if (exprNode_isDefined (e
))
1167 multiVal m
= exprNode_getValue (e
);
1169 if (multiVal_isInt (m
))
1171 return (multiVal_forceInt (m
) >= 0);
1175 ** This is not always true if programmer defines enum
1176 ** values, but then the constant should be known.
1179 if (ctype_isEnum (ctype_realType (e
->typ
)))
1189 ** a[x] - uses a but NOT a[]
1190 ** result sref = a[] (set/use in assignment)
1192 ** The syntax x[a] is also legal in C, and has the same
1193 ** semantics. If ind is an array, and arr is an int, flip
1198 exprNode_arrayFetch (/*@only@*/ exprNode e1
, /*@only@*/ exprNode e2
)
1201 ** error in arr, error propagates (no new messages)
1202 ** error in ind, assume valid and continue
1205 DPRINTF (("Array fetch: %s / %s",
1206 exprNode_unparse (e1
), exprNode_unparse (e2
)));
1208 if (exprNode_isError (e1
))
1211 return (exprNode_makeError ());
1217 ctype carr
= exprNode_getType (e1
);
1218 ctype crarr
= ctype_realType (carr
);
1221 ** this sets up funny aliasing, that leads to spurious
1222 ** splint errors. Hence, the i2 comments.
1225 /* evans 2001-09-09 added ctype_isKnown so there is no swap when e1 type is unknown */
1226 if (ctype_isKnown (crarr
)
1227 && !ctype_isRealArray (crarr
)
1228 && ctype_isRealNumeric (crarr
)
1229 && !exprNode_isError (e2
)
1230 && ctype_isRealAP (exprNode_getType (e2
))) /* fetch like 3[a] */
1235 carr
= exprNode_getType (arr
);
1236 crarr
= ctype_realType (carr
);
1244 DPRINTF (("arr: %s", exprNode_unparse (arr
)));
1246 if (sRef_possiblyNull (arr
->sref
))
1248 if (!usymtab_isGuarded (arr
->sref
))
1250 if (!context_inSizeof() )
1252 if (optgenerror (FLG_NULLDEREF
,
1253 message ("Index of %s pointer %q: %s",
1254 sRef_nullMessage (arr
->sref
),
1255 sRef_unparse (arr
->sref
),
1256 exprNode_unparse (arr
)),
1259 DPRINTF (("ref: %s", sRef_unparseFull (arr
->sref
)));
1260 sRef_showNullInfo (arr
->sref
);
1262 /* suppress future messages */
1263 sRef_setNullError (arr
->sref
);
1269 if (exprNode_isError (ind
))
1271 if ((ctype_isArrayPtr (crarr
)
1272 && !ctype_isFunction (crarr
))
1273 || ctype_isUnknown (carr
))
1275 exprNode ret
= exprNode_createPartialCopy (arr
);
1277 if (ctype_isKnown (carr
))
1279 ret
->typ
= ctype_baseArrayPtr (crarr
);
1283 ret
->typ
= ctype_unknown
;
1286 ret
->sref
= sRef_makeArrayFetch (arr
->sref
);
1288 ret
->kind
= XPR_FETCH
;
1291 ** Because of funny aliasing (when arr and ind are
1292 ** flipped) spurious errors would be reported here.
1295 /*@i2@*/ ret
->edata
= exprData_makePair (arr
, ind
);
1296 checkSafeUse (ret
, arr
->sref
);
1301 voptgenerror (FLG_TYPE
,
1302 message ("Array fetch from non-array (%t): %s[%s]", carr
,
1303 exprNode_unparse (e1
), exprNode_unparse (e2
)),
1305 exprNode_free (arr
);
1306 return (exprNode_makeError ());
1311 if (!ctype_isForceRealInt (&(ind
->typ
)))
1313 ctype rt
= ctype_realType (ind
->typ
);
1315 if (ctype_isChar (rt
))
1319 message ("Array fetch using non-integer, %t: %s[%s]",
1321 exprNode_unparse (e1
), exprNode_unparse (e2
)),
1324 else if (ctype_isEnum (rt
))
1328 message ("Array fetch using non-integer, %t: %s[%s]",
1330 exprNode_unparse (e1
), exprNode_unparse (e2
)),
1333 else if (ctype_isNumAbstract (rt
))
1336 (FLG_NUMABSTRACTINDEX
,
1337 message ("Array fetch using numabstract type, %t: %s[%s]",
1339 exprNode_unparse (e1
), exprNode_unparse (e2
)),
1346 message ("Array fetch using non-integer, %t: %s[%s]",
1348 exprNode_unparse (e1
), exprNode_unparse (e2
)),
1352 multiVal_free (ind
->val
);
1353 ind
->val
= multiVal_unknown ();
1356 if (ctype_isArrayPtr (crarr
) && !ctype_isFunction (crarr
))
1358 exprNode ret
= exprNode_createSemiCopy (arr
);
1359 multiVal m
= exprNode_getValue (ind
);
1361 ret
->typ
= ctype_baseArrayPtr (crarr
);
1362 ret
->kind
= XPR_FETCH
;
1364 if (multiVal_isInt (m
))
1366 int i
= (int) multiVal_forceInt (m
);
1368 if (sRef_isValid (arr
->sref
)) {
1369 ret
->sref
= sRef_makeArrayFetchKnown (arr
->sref
, i
);
1371 ret
->sref
= sRef_undefined
;
1376 ret
->sref
= sRef_makeArrayFetch (arr
->sref
);
1379 ret
->sets
= sRefSet_realNewUnion (arr
->sets
, ind
->sets
);
1380 ret
->msets
= sRefSet_realNewUnion (arr
->msets
, ind
->msets
);
1381 ret
->uses
= sRefSet_realNewUnion (arr
->uses
, ind
->uses
);
1383 /* (see comment on spurious errors above) */
1384 /*@i2@*/ ret
->edata
= exprData_makePair (arr
, ind
);
1386 exprNode_checkUse (ret
, ind
->sref
, ind
->loc
);
1387 exprNode_checkUse (ret
, arr
->sref
, arr
->loc
);
1393 if (ctype_isUnknown (carr
))
1395 exprNode ret
= exprNode_createPartialCopy (arr
);
1397 ret
->kind
= XPR_FETCH
;
1398 ret
->typ
= ctype_unknown
;
1399 ret
->sets
= sRefSet_union (ret
->sets
, ind
->sets
);
1400 ret
->msets
= sRefSet_union (ret
->msets
, ind
->msets
);
1401 ret
->uses
= sRefSet_union (ret
->uses
, ind
->uses
);
1403 /* (see comment on spurious errors above) */
1404 /*@i2@*/ ret
->edata
= exprData_makePair (arr
, ind
);
1406 exprNode_checkUse (ret
, ind
->sref
, ind
->loc
);
1407 exprNode_checkUse (ret
, arr
->sref
, arr
->loc
);
1414 message ("Array fetch from non-array (%t): %s[%s]", carr
,
1415 exprNode_unparse (e1
), exprNode_unparse (e2
)),
1418 exprNode_free (arr
);
1419 exprNode_free (ind
);
1421 return (exprNode_makeError ());
1431 checkArgs (uentry fcn
, /*@dependent@*/ exprNode f
, ctype t
,
1432 exprNodeList args
, exprNode ret
)
1434 return (checkArgsReal (fcn
, f
, ctype_argsFunction (t
), args
, FALSE
, ret
));
1438 ** checkPrintfArgs --- checks arguments for printf-like functions
1439 ** Arguments before ... have already been checked.
1440 ** The argument before the ... is a char *.
1441 ** argno is the format string argument.
1445 checkPrintfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f
, uentry fcn
,
1446 exprNodeList args
, exprNode ret
, int argno
)
1449 ** the last argument before the elips is the format string
1454 uentryList params
= uentry_getParams (fcn
);
1458 ** These should be ensured by checkSpecialFunction
1461 llassert (uentryList_size (params
) == argno
+ 1);
1462 llassert (uentry_isElipsisMarker (uentryList_getN (params
, argno
)));
1464 a
= exprNodeList_getN (args
, argno
- 1);
1465 formatloc
= fileloc_copy (exprNode_loc (a
));
1467 if (exprNode_isDefined (a
) && exprNode_isStringLiteral (a
)
1468 && exprNode_knownStringValue (a
))
1470 char *format
= cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a
)));
1471 char *code
= format
;
1473 int nargs
= exprNodeList_size (args
);
1475 while ((code
= strchr (code
, '%')) != NULL
)
1477 char *origcode
= code
;
1478 cstring codetext
= cstring_newEmpty ();
1479 char key
= *(++code
);
1480 ctype modtype
= ctype_int
;
1481 bool modified
= FALSE
;
1483 fileloc_addColumn (formatloc
, code
- ocode
);
1485 codetext
= cstring_appendChar (codetext
, key
);
1488 while (isFlagKey (key
))
1491 codetext
= cstring_appendChar (codetext
, key
);
1492 fileloc_incColumn (formatloc
);
1495 if (key
== 'm') /* skipped in syslog */
1500 /* ignore field width */
1501 while (isdigit ((int) key
) != 0)
1504 codetext
= cstring_appendChar (codetext
, key
);
1505 fileloc_incColumn (formatloc
);
1508 /* ignore precision */
1512 codetext
= cstring_appendChar (codetext
, key
);
1513 fileloc_incColumn (formatloc
);
1516 ** In printf, '*' means: read the next arg as an int for the
1517 ** field width. This seems to be missing from my copy of the
1518 ** standard x3.159-1989. Setion 4.9.6.1 refers to * (described
1519 ** later) but never does.
1524 ; /* don't do anything --- handle later */
1528 while (isdigit ((int) key
) != 0)
1531 codetext
= cstring_appendChar (codetext
, key
);
1532 fileloc_incColumn (formatloc
);
1539 modtype
= ctype_sint
; /* short */
1541 codetext
= cstring_appendChar (codetext
, key
);
1542 fileloc_incColumn (formatloc
);
1544 else if (key
== 'l' || key
== 'L')
1546 modtype
= ctype_lint
; /* long */
1548 codetext
= cstring_appendChar (codetext
, key
);
1549 fileloc_incColumn (formatloc
);
1551 if (key
== 'l' || key
== 'L') {
1552 modtype
= ctype_llint
; /* long long */
1554 codetext
= cstring_appendChar (codetext
, key
);
1555 fileloc_incColumn (formatloc
);
1563 /* now, key = type of conversion to apply */
1565 fileloc_incColumn (formatloc
);
1573 message ("No argument corresponding to %q format "
1574 "code %d (%%%s): \"%s\"",
1575 uentry_getName (fcn
),
1577 cstring_fromChars (format
)),
1580 if (fileloc_isDefined (formatloc
)
1581 && context_getFlag (FLG_SHOWCOL
))
1583 llgenindentmsg (cstring_makeLiteral ("Corresponding format code"),
1591 a
= exprNodeList_getN (args
, i
);
1594 if (!exprNode_isError (a
))
1600 case '*': /* int argument for fieldwidth */
1601 expecttype
= ctype_int
;
1602 *(--code
) = '%'; /* convert it for next code */
1603 fileloc_subColumn (formatloc
, 1);
1604 /*@switchbreak@*/ break;
1607 expecttype
= ctype_combine (ctype_uint
, modtype
);
1608 /*@switchbreak@*/ break;
1610 case 'i': /* int argument */
1612 expecttype
= ctype_combine (ctype_int
, modtype
);
1613 /*@switchbreak@*/ break;
1615 case 'x': /* unsigned int */
1617 expecttype
= ctype_combine (ctype_uint
, modtype
);
1619 /*@switchbreak@*/ break;
1625 case 'f': /* double */
1626 expecttype
= ctype_combine (ctype_double
, modtype
);
1627 /*@switchbreak@*/ break;
1629 case 'c': /* int converted to char (check its a char?) */
1630 expecttype
= ctype_makeConj (ctype_int
,
1631 ctype_makeConj (ctype_char
,
1633 /* evans 2001-10-05 - changed to reflect correct ISO spec:
1634 int converted to char */
1636 /*@switchbreak@*/ break;
1638 case 's': /* string */
1639 expecttype
= ctype_string
;
1640 /*@switchbreak@*/ break;
1643 while (((key
= *(++code
)) != ']')
1646 codetext
= cstring_appendChar (codetext
, key
);
1647 fileloc_incColumn (formatloc
);
1653 (message ("Bad character set format: %s",
1654 cstring_fromChars (origcode
)));
1657 expecttype
= ctype_string
;
1658 /*@switchbreak@*/ break;
1660 case 'p': /* pointer */
1661 expecttype
= ctype_makePointer (ctype_void
);
1662 /* need not be defined */
1663 uentry_setDefState (regArg
, SS_RELDEF
);
1664 sRef_setPosNull (uentry_getSref (regArg
),
1667 /*@switchbreak@*/ break;
1669 case 'n': /* pointer to int, modified by call! */
1670 expecttype
= ctype_combine (ctype_makePointer (ctype_int
), modtype
);
1672 uentry_setDefState (regArg
, SS_ALLOCATED
); /* corresponds to out */
1673 /*@switchbreak@*/ break;
1675 case 'm': /* in a syslog, it doesn't consume an argument */
1676 /* should check we're really doing syslog */
1678 /*@switchbreak@*/ break;
1682 expecttype
= ctype_unknown
;
1686 message ("Unrecognized format code: %s",
1687 cstring_fromChars (origcode
)),
1688 fileloc_isDefined (formatloc
)
1689 ? formatloc
: g_currentloc
);
1691 /*@switchbreak@*/ break;
1694 if (!(exprNode_matchArgType (expecttype
, a
)))
1696 if (ctype_isVoidPointer (expecttype
)
1697 && ctype_isRealAbstract (a
->typ
)
1698 && (context_getFlag (FLG_ABSTVOIDP
)))
1704 if (llgenformattypeerror
1705 (expecttype
, exprNode_undefined
,
1707 message ("Format argument %d to %q (%%%s) expects "
1710 uentry_getName (fcn
),
1713 a
->typ
, exprNode_unparse (a
)),
1716 if (fileloc_isDefined (formatloc
)
1717 && context_getFlag (FLG_SHOWCOL
))
1720 (cstring_makeLiteral
1721 ("Corresponding format code"),
1728 uentry_setType (regArg
, expecttype
);
1729 checkOneArg (regArg
, a
, f
, FALSE
, i
+1, nargs
);
1731 if (ctype_equal (expecttype
, ctype_string
))
1733 exprNode_checkUse (a
, sRef_makePointer (a
->sref
), a
->loc
);
1736 uentry_setType (regArg
, ctype_unknown
);
1737 uentry_fixupSref (regArg
);
1741 exprNode_checkCallModifyVal (a
->sref
, args
, f
, ret
);
1752 cstring_free (codetext
);
1757 voptgenerror (FLG_TYPE
,
1758 message ("Format string for %q has %d arg%&, given %d",
1759 uentry_getName (fcn
), i
- argno
, nargs
- argno
),
1765 /* no checking possible for compile-time unknown format strings */
1766 if (exprNode_isDefined (a
))
1770 message ("Format string parameter to %s is not a compile-time constant: %s",
1771 exprNode_unparse (f
),
1772 exprNode_unparse (a
)),
1777 fileloc_free (formatloc
);
1781 checkScanfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f
, uentry fcn
,
1782 exprNodeList args
, exprNode ret
, int argno
)
1786 uentryList params
= uentry_getParams (fcn
);
1790 ** These should be ensured by checkSpecialFunction
1793 llassert (uentryList_size (params
) == argno
+ 1);
1794 llassert (uentry_isElipsisMarker (uentryList_getN (params
, argno
)));
1796 a
= exprNodeList_getN (args
, argno
- 1);
1797 formatloc
= fileloc_copy (exprNode_loc (a
));
1799 if (exprNode_isDefined (a
) && exprNode_isStringLiteral (a
)
1800 && exprNode_knownStringValue (a
))
1802 char *format
= cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a
)));
1803 char *code
= format
;
1805 int nargs
= exprNodeList_size (args
);
1807 while ((code
= strchr (code
, '%')) != NULL
)
1809 char *origcode
= code
;
1810 char key
= *(++code
);
1811 cstring codetext
= cstring_newEmpty ();
1812 ctype modtype
= ctype_int
;
1813 char modifier
= '\0';
1814 bool modified
= TRUE
;
1815 bool ignore
= FALSE
;
1817 codetext
= cstring_appendChar (codetext
, key
);
1818 fileloc_addColumn (formatloc
, code
- ocode
);
1821 ** this is based on ANSI standard library description of fscanf
1822 ** (from ANSI standard X3.159-1989, 4.9.6.1)
1825 /* '*' suppresses assignment (does not need match argument) */
1830 codetext
= cstring_appendChar (codetext
, key
);
1833 fileloc_incColumn (formatloc
);
1836 /* ignore field width */
1837 while (isdigit ((int) key
) != 0)
1840 codetext
= cstring_appendChar (codetext
, key
);
1841 fileloc_incColumn (formatloc
);
1846 modtype
= ctype_sint
; /* short */
1848 codetext
= cstring_appendChar (codetext
, key
);
1849 fileloc_incColumn (formatloc
);
1851 else if (key
== 'l' || key
== 'L')
1853 modtype
= ctype_lint
; /* long */
1857 codetext
= cstring_appendChar (codetext
, key
);
1859 fileloc_incColumn (formatloc
);
1861 if (key
== 'l' || key
== 'L') {
1862 modtype
= ctype_llint
; /* long long */
1864 codetext
= cstring_appendChar (codetext
, key
);
1865 fileloc_incColumn (formatloc
);
1873 /* now, key = type of conversion to apply */
1875 fileloc_incColumn (formatloc
);
1889 message ("No argument corresponding to %q format "
1890 "code %d (%%%s): \"%s\"",
1891 uentry_getName (fcn
),
1893 cstring_fromChars (format
)),
1896 if (fileloc_isDefined (formatloc
)
1897 && context_getFlag (FLG_SHOWCOL
))
1900 (cstring_makeLiteral ("Corresponding format code"),
1908 a
= exprNodeList_getN (args
, i
);
1911 if (!exprNode_isError (a
))
1917 case '*': /* int argument for fieldwidth */
1918 expecttype
= ctype_makePointer (ctype_int
);
1919 *(--code
) = '%'; /* convert it for next code */
1920 fileloc_subColumn (formatloc
, 1);
1921 /*@switchbreak@*/ break;
1924 expecttype
= ctype_makePointer (ctype_combine (ctype_uint
, modtype
));
1925 /*@switchbreak@*/ break;
1929 expecttype
= ctype_makePointer (ctype_combine (ctype_int
, modtype
));
1930 /*@switchbreak@*/ break;
1933 case 'X': /* unsigned int */
1934 expecttype
= ctype_makePointer (ctype_combine (ctype_uint
, modtype
));
1935 /*@switchbreak@*/ break;
1942 /* printf is double, scanf is float! */
1944 if (modifier
== 'l')
1946 expecttype
= ctype_makePointer (ctype_double
);
1948 else if (modifier
== 'L')
1950 expecttype
= ctype_makePointer (ctype_ldouble
);
1954 llassert (modifier
== '\0');
1955 expecttype
= ctype_makePointer (ctype_float
);
1957 /*@switchbreak@*/ break;
1959 case 'c': /* int converted to char (check its a char?) */
1960 expecttype
= ctype_makePointer (ctype_makeConj (ctype_char
, ctype_uchar
));
1961 /*@switchbreak@*/ break;
1963 case 's': /* string */
1964 expecttype
= ctype_string
;
1965 /*@switchbreak@*/ break;
1969 while (((key
= *(++code
)) != ']')
1972 codetext
= cstring_appendChar (codetext
, key
);
1973 fileloc_incColumn (formatloc
);
1979 (message ("Bad character set format: %s",
1980 cstring_fromChars (origcode
)));
1983 expecttype
= ctype_string
;
1984 /*@switchbreak@*/ break;
1987 case 'p': /* pointer */
1990 message ("Format code should not be used in scanf: %s",
1991 cstring_fromChars (origcode
)),
1992 fileloc_isDefined (formatloc
)
1993 ? formatloc
: g_currentloc
);
1995 expecttype
= ctype_unknown
;
1996 /*@switchbreak@*/ break;
1998 case 'n': /* pointer to int, modified by call! */
1999 expecttype
= ctype_makePointer (ctype_int
);
2000 /*@switchbreak@*/ break;
2003 expecttype
= ctype_unknown
;
2007 message ("Unrecognized format code: %s",
2008 cstring_fromChars (origcode
)),
2009 fileloc_isDefined (formatloc
)
2010 ? formatloc
: g_currentloc
);
2012 /*@switchbreak@*/ break;
2015 if (!(exprNode_matchArgType (expecttype
, a
)))
2017 if (ctype_isVoidPointer (expecttype
)
2018 && ctype_isRealAbstract (a
->typ
)
2019 && (context_getFlag (FLG_ABSTVOIDP
)))
2025 if (llgenformattypeerror
2026 (expecttype
, exprNode_undefined
,
2028 message ("Format argument %d to %q (%%%s) expects "
2031 uentry_getName (fcn
),
2032 codetext
, expecttype
,
2033 a
->typ
, exprNode_unparse (a
)),
2036 if (fileloc_isDefined (formatloc
)
2037 && context_getFlag (FLG_SHOWCOL
))
2040 (cstring_makeLiteral
2041 ("Corresponding format code"),
2048 uentry_setType (outArg
, expecttype
);
2049 checkOneArg (outArg
, a
, f
, FALSE
, i
+1, nargs
);
2050 uentry_setType (outArg
, ctype_unknown
);
2051 uentry_fixupSref (outArg
);
2055 exprNode_checkCallModifyVal (a
->sref
, args
, f
, ret
);
2060 /* a->sref = sRef_undefined; */
2067 cstring_free (codetext
);
2072 voptgenerror (FLG_TYPE
,
2073 message ("Format string for %q has %d arg%&, given %d",
2074 uentry_getName (fcn
), i
- argno
, nargs
- argno
),
2080 /* no checking possible for compile-time unknown format strings */
2083 fileloc_free (formatloc
);
2087 checkMessageArgs (/*@notnull@*/ /*@dependent@*/ exprNode f
,
2090 /*@unused@*/ int argno
)
2093 ** the last argument before the elips is the format string
2100 a
= exprNodeList_getN (args
, argno
- 1);
2101 formatloc
= fileloc_copy (exprNode_loc (a
));
2103 if (ctype_isUnknown (cstringType
)) {
2104 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
2106 cstringType
= usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
2110 if (ctype_isUnknown (ctypeType
)) {
2111 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
2113 ctypeType
= usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
2117 if (ctype_isUnknown (filelocType
)) {
2118 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
2120 filelocType
= usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
2124 if (exprNode_isDefined (a
) && exprNode_isStringLiteral (a
)
2125 && exprNode_knownStringValue (a
))
2127 cstring format
= multiVal_forceString (exprNode_getValue (a
));
2128 char *code
= cstring_toCharsSafe (format
);
2130 int nargs
= exprNodeList_size (args
);
2132 while ((code
= strchr (code
, '%')) != NULL
)
2134 char *origcode
= code
;
2135 char key
= *(++code
);
2136 cstring codetext
= cstring_newEmpty ();
2137 bool isOnly
= FALSE
;
2139 codetext
= cstring_appendChar (codetext
, key
);
2141 fileloc_addColumn (formatloc
, code
- ocode
);
2143 while (key
>= '0' && key
<= '9')
2146 codetext
= cstring_appendChar (codetext
, key
);
2147 fileloc_incColumn (formatloc
);
2151 fileloc_incColumn (formatloc
);
2155 if (key
== '&') /* plural marker */
2164 message ("Message missing format arg %d (%%%s): \"%s\"",
2165 i
+ 1, codetext
, format
),
2171 a
= exprNodeList_getN (args
, i
);
2175 if (!exprNode_isError (a
))
2179 /*@-loopswitchbreak@*/
2185 expecttype
= ctype_char
; break;
2187 expecttype
= cstringType
; break;
2189 expecttype
= cstringType
; isOnly
= TRUE
; break;
2191 expecttype
= cstringType
; isOnly
= TRUE
; break;
2192 case 'd': expecttype
= ctype_int
; break;
2193 case 'u': expecttype
= ctype_uint
; break;
2194 case 'w': expecttype
= ctype_ulint
; break;
2195 case 'f': expecttype
= ctype_float
; break;
2196 case 'b': expecttype
= ctype_bool
; break;
2197 case 't': expecttype
= ctypeType
; break;
2199 expecttype
= ctype_makePointer (ctype_void
);
2200 /* need not be defined */
2201 uentry_setDefState (regArg
, SS_RELDEF
);
2202 sRef_setPosNull (uentry_getSref (regArg
),
2205 /*@switchbreak@*/ break;
2206 case 'l': expecttype
= filelocType
; break;
2207 case '&': /* a wee bit of a hack methinks */
2208 expecttype
= ctype_int
;
2210 case 'r': expecttype
= ctype_bool
; break;
2212 expecttype
= ctype_unknown
;
2215 message ("Unrecognized format code: %s",
2216 cstring_fromChars (origcode
)),
2217 fileloc_isDefined (formatloc
)
2218 ? formatloc
: g_currentloc
);
2221 /*@=loopswitchbreak@*/
2223 if (!(exprNode_matchArgType (expecttype
, a
)))
2225 if (ctype_isVoidPointer (expecttype
)
2226 && ctype_isRealAbstract (a
->typ
)
2227 && (context_getFlag (FLG_ABSTVOIDP
)))
2233 if (llgenformattypeerror
2234 (expecttype
, exprNode_undefined
,
2236 message ("Format argument %d to %q (%%%s) expects "
2239 uentry_getName (fcn
),
2240 codetext
, expecttype
,
2241 a
->typ
, exprNode_unparse (a
)),
2244 if (fileloc_isDefined (formatloc
)
2245 && context_getFlag (FLG_SHOWCOL
))
2248 (cstring_makeLiteral
2249 ("Corresponding format code"),
2256 if (ctype_equal (expecttype
, cstringType
))
2260 checkOneArg (csOnlyArg
, a
, f
, FALSE
, i
+1, nargs
);
2261 uentry_fixupSref (csOnlyArg
);
2265 checkOneArg (csArg
, a
, f
, FALSE
, i
+1, nargs
);
2266 uentry_fixupSref (csArg
);
2271 checkOneArg (regArg
, a
, f
, FALSE
, i
+1, nargs
);
2272 uentry_fixupSref (regArg
);
2278 cstring_free (codetext
);
2283 voptgenerror (FLG_TYPE
,
2284 message ("Format string for %q has %d arg%&, given %d",
2285 uentry_getName (fcn
), i
- argno
, nargs
-argno
),
2291 /* no checking possible for compile-time unknown format strings */
2294 fileloc_free (formatloc
);
2298 checkExpressionDefinedAux (/*@notnull@*/ exprNode e1
,
2299 /*@notnull@*/ exprNode e2
,
2305 bool hadUncon
= FALSE
;
2307 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e1
->sref
)) &&
2308 sRefSet_hasUnconstrained (sets2
))
2311 (FLG_EVALORDERUNCON
,
2313 ("Expression may have undefined behavior (%q used in right operand "
2314 "may set global variable %q used in left operand): %s %s %s",
2315 sRefSet_unparseUnconstrained (sets2
),
2316 sRef_unparse (sRef_getRootBase (e1
->sref
)),
2317 exprNode_unparse (e1
), lltok_unparse (op
), exprNode_unparse (e2
)),
2321 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e2
->sref
)) &&
2322 sRefSet_hasUnconstrained (sets1
))
2325 (FLG_EVALORDERUNCON
,
2327 ("Expression has undefined behavior (%q used in left operand "
2328 "may set global variable %q used in right operand): %s %s %s",
2329 sRefSet_unparseUnconstrained (sets1
),
2330 sRef_unparse (e2
->sref
),
2331 exprNode_unparse (e1
), lltok_unparse (op
), exprNode_unparse (e2
)),
2335 sRefSet_realElements (e1
->uses
, sr
)
2337 if (sRef_isMeaningful (sr
) && sRefSet_member (sets2
, sr
))
2342 ("Expression has undefined behavior (left operand uses %q, "
2343 "modified by right operand): %s %s %s",
2345 exprNode_unparse (e1
), lltok_unparse (op
), exprNode_unparse (e2
)),
2348 } end_sRefSet_realElements
;
2350 sRefSet_realElements (sets1
, sr
)
2352 if (sRef_isMeaningful (sr
))
2354 if (sRef_same (sr
, e2
->sref
))
2359 ("Expression has undefined behavior (value of right operand "
2360 "modified by left operand): %s %s %s",
2361 exprNode_unparse (e1
), lltok_unparse (op
), exprNode_unparse (e2
)),
2364 else if (sRefSet_member (e2
->uses
, sr
))
2369 ("Expression has undefined behavior (left operand modifies %q, "
2370 "used by right operand): %s %s %s",
2372 exprNode_unparse (e1
), lltok_unparse (op
), exprNode_unparse (e2
)),
2377 if (sRefSet_member (sets2
, sr
))
2379 if (sRef_isUnconstrained (sr
))
2387 hadUncon
= optgenerror
2388 (FLG_EVALORDERUNCON
,
2390 ("Expression may have undefined behavior. Left operand "
2391 "calls %q; right operand calls %q. The unconstrained "
2392 "functions may modify global state used by "
2393 "the other operand): %s %s %s",
2394 sRefSet_unparseUnconstrained (sets1
),
2395 sRefSet_unparseUnconstrained (sets2
),
2396 exprNode_unparse (e1
), lltok_unparse (op
),
2397 exprNode_unparse (e2
)),
2406 ("Expression has undefined behavior (both "
2407 "operands modify %q): %s %s %s",
2409 exprNode_unparse (e1
),
2410 lltok_unparse (op
), exprNode_unparse (e2
)),
2416 } end_sRefSet_realElements
;
2419 static void checkExpressionDefined (exprNode e1
, exprNode e2
, lltok op
)
2421 bool hasError
= FALSE
;
2423 if (exprNode_isError (e1
) || exprNode_isError (e2
))
2428 if (sRefSet_member (e2
->sets
, e1
->sref
))
2430 if (e2
->kind
== XPR_CALL
)
2436 hasError
= optgenerror
2438 message ("Expression has undefined behavior "
2439 "(value of left operand %s is modified "
2440 "by right operand %s): %s %s %s",
2441 exprNode_unparse (e1
),
2442 exprNode_unparse (e2
),
2443 exprNode_unparse (e1
), lltok_unparse (op
),
2444 exprNode_unparse (e2
)),
2449 if (context_getFlag (FLG_EVALORDERUNCON
))
2451 if (sRefSet_member (e2
->msets
, e1
->sref
))
2453 if (e2
->kind
== XPR_CALL
)
2459 hasError
= optgenerror
2462 ("Expression has undefined behavior (value of left "
2463 "operand may be modified by right operand): %s %s %s",
2464 exprNode_unparse (e1
), lltok_unparse (op
),
2465 exprNode_unparse (e2
)),
2473 checkExpressionDefinedAux (e1
, e2
, e1
->sets
, e2
->sets
, op
, FLG_EVALORDER
);
2475 if (context_maybeSet (FLG_EVALORDERUNCON
))
2477 checkExpressionDefinedAux (e1
, e2
, e1
->msets
,
2478 e2
->msets
, op
, FLG_EVALORDERUNCON
);
2483 static void checkSequencing (exprNode p_f
, exprNodeList p_args
);
2486 checkArgsReal (uentry fcn
, /*@dependent@*/ exprNode f
, uentryList cl
,
2487 exprNodeList args
, bool isIter
, exprNode ret
)
2491 if (!exprNode_isError (f
))
2493 if (!uentryList_isMissingParams (cl
))
2495 int nargs
= exprNodeList_size (args
);
2496 int expectargs
= uentryList_size (cl
);
2500 if (expectargs
== 0)
2508 message ("Iter %q invoked with %d args, "
2510 uentry_getName (fcn
),
2518 message ("Function %s called with %d args, "
2520 exprNode_unparse (f
), nargs
),
2527 last
= uentry_getType (uentryList_getN (cl
, expectargs
- 1));
2529 exprNodeList_reset (args
);
2531 uentryList_elements (cl
, current
)
2533 ctype ct
= uentry_getType (current
);
2536 if (ctype_isElips (ct
))
2539 ** do special checking for printf/scanf library functions
2541 ** this is kludgey code, just for handling the special case
2545 if (uentry_isPrintfLike (fcn
))
2547 checkPrintfArgs (f
, fcn
, args
, ret
, i
);
2550 else if (uentry_isScanfLike (fcn
))
2552 checkScanfArgs (f
, fcn
, args
, ret
, i
);
2555 else if (uentry_isMessageLike (fcn
))
2557 checkMessageArgs (f
, fcn
, args
, i
);
2562 llassert (!uentry_isSpecialFunction (fcn
));
2565 nargs
= expectargs
; /* avoid errors */
2570 if (i
>= nargs
) break;
2572 a
= exprNodeList_current (args
);
2573 exprNodeList_advance (args
);
2577 if (exprNode_isError (a
))
2584 probably necessary? I'm not sure about this one
2585 checkMacroParen (a);
2588 f
->guards
= guardSet_union (f
->guards
, a
->guards
);
2590 DPRINTF (("match arg: %s / %s", ctype_unparse (ct
), ctype_unparse (a
->typ
)));
2592 if (!(exprNode_matchArgType (ct
, a
)))
2594 DPRINTF (("Args mismatch!"));
2596 if (ctype_isVoidPointer (ct
)
2597 && (ctype_isPointer (a
->typ
)
2598 && (ctype_isRealAbstract (ctype_baseArrayPtr (a
->typ
)))))
2603 ("Pointer to abstract type (%t) used "
2605 "(arg %d to %q): %s",
2607 uentry_getName (fcn
),
2608 exprNode_unparse (a
)),
2616 (ct
, exprNode_undefined
,
2619 ("Iter %q expects arg %d to "
2620 "be %t gets %t: %s",
2621 uentry_getName (fcn
),
2622 i
, ct
, a
->typ
, exprNode_unparse (a
)),
2633 ("Function %q expects arg %d to be %t gets %t: %s",
2634 uentry_getName (fcn
),
2635 i
, ct
, a
->typ
, exprNode_unparse (a
)),
2638 DPRINTF (("Types: %s / %s",
2640 ctype_unparse (a
->typ
)));
2644 ** Clear null marker for abstract types.
2645 ** (It is not revealed, so suppress future messages.)
2648 if (ctype_isAbstract (a
->typ
))
2650 sRef_setNullUnknown (exprNode_getSref (a
), a
->loc
);
2657 } end_uentryList_elements
;
2660 if (expectargs
!= nargs
) /* note: not != since we may have ... */
2662 if (ctype_isElips (last
))
2666 message ("Function %s called with %d args, expects at least %d",
2667 exprNode_unparse (f
),
2668 nargs
, expectargs
- 1),
2677 message ("Iter %q invoked with %d args, expects %d",
2678 uentry_getName (fcn
), nargs
, expectargs
),
2685 message ("Function %s called with %d args, expects %d",
2686 exprNode_unparse (f
),
2699 ** Check for undefined code sequences in function arguments:
2701 ** one parameter sets something used by another parameter
2702 ** one parameter sets something set by another parameter
2706 checkSequencingOne (exprNode f
, exprNodeList args
,
2707 /*@notnull@*/ exprNode el
, int argno
)
2710 ** Do second loop, iff +undefunspec
2714 int numloops
= context_maybeSet (FLG_EVALORDERUNCON
) ? 2 : 1;
2716 for (checkloop
= 0; checkloop
< numloops
; checkloop
++)
2722 thissets
= el
->sets
;
2726 llassert (checkloop
== 1);
2727 thissets
= el
->msets
;
2730 sRefSet_realElements (thissets
, thisset
)
2734 /*@access exprNodeList@*/
2735 for (j
= 0; j
< args
->nelements
; j
++)
2737 exprNode jl
= args
->elements
[j
];
2738 int thisargno
= j
+ 1;
2740 if (thisargno
!= argno
&& exprNode_isDefined (jl
))
2742 sRefSet otheruses
= jl
->uses
;
2744 if (sRef_isFileOrGlobalScope (sRef_getRootBase (jl
->sref
)) &&
2745 sRefSet_hasUnconstrained (thissets
))
2748 (FLG_EVALORDERUNCON
,
2751 ("%q used in argument %d may set "
2752 "global variable %q used by argument %d: %s(%q)",
2753 cstring_capitalizeFree (sRefSet_unparseUnconstrained (thissets
)),
2756 sRef_unparse (sRef_getRootBase (jl
->sref
)),
2758 exprNode_unparse (f
), exprNodeList_unparse (args
)),
2762 if (sRefSet_member (otheruses
, thisset
))
2764 if (sRef_isUnconstrained (thisset
))
2767 (FLG_EVALORDERUNCON
,
2769 ("Unconstrained functions used in arguments %d (%q) "
2770 "and %d (%s) may modify "
2771 "or use global state in undefined way: %s(%q)",
2773 sRefSet_unparseUnconstrainedPlain (otheruses
),
2775 sRef_unconstrainedName (thisset
),
2776 exprNode_unparse (f
),
2777 exprNodeList_unparse (args
)),
2785 ("Argument %d modifies %q, used by argument %d "
2786 "(order of evaluation of actual parameters is "
2787 "undefined): %s(%q)",
2788 argno
, sRef_unparse (thisset
), thisargno
,
2789 exprNode_unparse (f
), exprNodeList_unparse (args
)),
2795 sRefSet othersets
= jl
->sets
;
2797 if (sRefSet_member (othersets
, thisset
))
2799 if (sRef_isUnconstrained (thisset
))
2802 (FLG_EVALORDERUNCON
,
2804 ("Unconstrained functions used in "
2805 "arguments %d (%q) and %d (%s) may modify "
2806 "or use global state in undefined way: %s(%q)",
2808 sRefSet_unparseUnconstrainedPlain (othersets
),
2810 sRef_unconstrainedName (thisset
),
2811 exprNode_unparse (f
), exprNodeList_unparse (args
)),
2819 ("Argument %d modifies %q, set by argument %d (order of"
2820 " evaluation of actual parameters is undefined): %s(%q)",
2821 argno
, sRef_unparse (thisset
), thisargno
,
2822 exprNode_unparse (f
), exprNodeList_unparse (args
)),
2829 /*@noaccess exprNodeList@*/
2830 } end_sRefSet_realElements
;
2835 checkSequencing (exprNode f
, exprNodeList args
)
2837 if (exprNodeList_size (args
) > 1)
2842 /*@access exprNodeList*/
2844 for (i
= 0; i
< args
->nelements
; i
++)
2846 el
= args
->elements
[i
];
2848 if (!exprNode_isError (el
))
2850 checkSequencingOne (f
, args
, el
, i
+ 1);
2853 /*@noaccess exprNodeList*/
2858 ** requires le = exprNode_getUentry (f)
2862 checkGlobMods (/*@notnull@*/ /*@dependent@*/ exprNode f
,
2863 uentry le
, exprNodeList args
,
2864 /*@notnull@*/ exprNode ret
, int specialArgs
)
2866 bool isSpec
= FALSE
;
2867 bool hasMods
= FALSE
;
2869 globSet usesGlobs
= globSet_undefined
;
2870 sRefSet mods
= sRefSet_undefined
;
2871 bool freshMods
= FALSE
;
2872 uentryList params
= uentryList_undefined
;
2874 DPRINTF (("Check glob mods: %s", exprNode_unparse (ret
)));
2877 ** check globals and modifies
2882 if (!uentry_isValid (le
))
2884 ctype fr
= ctype_realType (f
->typ
);
2886 if (ctype_isFunction (fr
))
2888 params
= ctype_argsFunction (fr
);
2892 params
= uentryList_missingParams
;
2895 if (!context_getFlag (FLG_MODNOMODS
)
2896 && !context_getFlag (FLG_GLOBUNSPEC
))
2898 checkUnspecCall (f
, params
, args
);
2904 fname
= uentry_rawName (le
);
2908 if (uentry_isFunction (le
))
2910 params
= uentry_getParams (le
);
2911 mods
= uentry_getMods (le
);
2912 hasMods
= uentry_hasMods (le
);
2913 usesGlobs
= uentry_getGlobs (le
);
2914 isSpec
= uentry_isSpecified (le
);
2916 else /* not a function */
2918 ctype ct
= ctype_realType (uentry_getType (le
));
2920 llassertprint (uentry_isVar (le
) && ctype_isFunction (ct
),
2921 ("checkModGlobs: uentry not a function: %s",
2922 uentry_unparse (le
)));
2924 params
= ctype_argsFunction (ct
);
2925 return; /* No checking for non-function */
2934 globSet_allElements (usesGlobs
, el
)
2936 if (sRef_isValid (el
))
2938 if (sRef_isInternalState (el
) || sRef_isSystemState (el
))
2940 context_usedGlobal (el
);
2941 exprNode_checkUse (f
, el
, f
->loc
);
2943 if (context_checkInternalUse ())
2945 if (!context_globAccess (el
))
2947 if (sRef_isSystemState (el
)
2948 && !context_getFlag (FLG_MODFILESYSTEM
))
2957 ("Called procedure %s may access %q, but "
2958 "globals list does not include globals %s",
2959 exprNode_unparse (f
),
2961 cstring_makeLiteralTemp (sRef_isInternalState (el
)
2969 else if (sRef_isNothing (el
) || sRef_isSpecState (el
))
2975 uentry gle
= sRef_getUentry (el
);
2976 sRef sr
= sRef_updateSref (el
);
2978 if (sRef_isUndefGlob (el
))
2980 sRef_setDefined (sr
, f
->loc
);
2981 exprNode_checkSet (f
, sr
);
2989 if (sRef_isAllocated (el
))
2991 exprNode_checkSet (f
, sr
);
2995 if (sRef_isStateUndefined (sr
))
3000 ("%s %q used by function undefined before call: %s",
3001 sRef_getScopeName (sr
),
3003 exprNode_unparse (f
)),
3005 sRef_setDefined (sr
, f
->loc
);
3007 exprNode_checkUse (f
, sr
, f
->loc
);
3010 checkGlobUse (gle
, TRUE
, f
);
3013 if (sRef_isKilledGlob (el
))
3015 sRef_kill (sr
, f
->loc
);
3016 context_usedGlobal (sr
);
3020 } end_globSet_allElements
;
3026 if (context_hasMods () || context_getFlag (FLG_MODNOMODS
))
3028 sRefSet smods
= sRefSet_undefined
;
3031 ** NEED to check for modifies anything
3035 ** check each sRef that called function modifies (ml), is
3041 sRefSet_allElements (mods
, s
) /* s is something which may be modified */
3043 DPRINTF (("Check modify: %s", sRef_unparse (s
)));
3045 if (sRef_isKindSpecial (s
))
3047 if (sRef_isSpecInternalState (s
))
3049 if (context_getFlag (FLG_MODINTERNALSTRICT
))
3051 exprNode_checkCallModifyVal (s
, args
, f
, ret
);
3055 sRefSet mmods
= context_modList ();
3057 sRefSet_allElements (mmods
, el
)
3059 if (sRef_isInternalState (el
))
3061 sRef_setModified (el
);
3063 } end_sRefSet_allElements
;
3068 exprNode_checkCallModifyVal (s
, args
, f
, ret
);
3073 sRef rb
= sRef_getRootBase (s
);
3075 if (sRef_isFileOrGlobalScope (rb
))
3077 context_usedGlobal (rb
);
3080 if (sRef_isFileStatic (s
)
3081 && !fileId_equal (fileloc_fileId (f
->loc
),
3082 fileloc_fileId (uentry_whereDefined (le
))))
3084 smods
= sRefSet_insert (smods
, s
);
3088 exprNode_checkCallModifyVal (s
, args
, f
, ret
);
3091 } end_sRefSet_allElements
;
3096 ** Static elements in modifies set can have nasty consequences.
3097 ** (I think...have not been able to reproduce a possible bug.)
3100 if (!sRefSet_isDefined (smods
))
3102 mods
= sRefSet_newCopy (mods
);
3105 sRefSet_allElements (smods
, el
)
3107 bool res
= sRefSet_delete (mods
, el
);
3110 } end_sRefSet_allElements
;
3112 sRefSet_free (smods
);
3117 else if (sRefSet_isDefined (mods
))
3118 { /* just check observers */
3121 sRefSet_allElements (mods
, s
) /* s is something which may be modified */
3123 sRef rb
= sRef_getRootBase (s
);
3127 if (sRef_isParam (rb
))
3129 sRef b
= sRef_fixBaseParam (s
, args
);
3131 if (sRef_isObserver (b
))
3133 exprNode e
= exprNodeList_nth (args
, sRef_getParam (rb
));
3137 message ("Function call may modify observer%q: %s",
3138 sRef_unparsePreOpt (b
), exprNode_unparse (e
)),
3141 sRef_showExpInfo (b
);
3145 } end_sRefSet_allElements
;
3149 if (!hasMods
) /* no specified modifications */
3151 if (context_getFlag (FLG_MODOBSERVERUNCON
))
3153 exprNodeList_elements (args
, e
)
3155 if (exprNode_isDefined (e
))
3157 sRef s
= exprNode_getSref (e
);
3159 if (sRef_isObserver (s
)
3160 && ctype_isMutable (sRef_getType (s
)))
3163 (FLG_MODOBSERVERUNCON
,
3165 ("Call to unconstrained function %s may modify observer%q: %s",
3166 exprNode_unparse (f
),
3167 sRef_unparsePreOpt (s
), exprNode_unparse (e
)),
3170 sRef_showExpInfo (s
);
3174 } end_exprNodeList_elements
;
3179 checkAnyCall (f
, fname
, params
, args
, hasMods
, mods
, isSpec
, specialArgs
);
3181 ret
->uses
= sRefSet_union (ret
->uses
, f
->uses
);
3182 ret
->sets
= sRefSet_union (ret
->sets
, f
->sets
);
3183 ret
->msets
= sRefSet_union (ret
->msets
, f
->msets
);
3188 ** Spurious errors reported, because splint can't tell
3189 ** mods must be fresh if freshMods is true.
3192 /*@i@*/ sRefSet_free (mods
);
3198 void checkGlobUse (uentry glob
, bool isCall
, /*@notnull@*/ exprNode e
)
3200 if (uentry_isVar (glob
))
3202 if (context_inFunctionLike ())
3204 sRef sr
= uentry_getSref (glob
);
3206 context_usedGlobal (sr
);
3208 if (context_checkGlobUse (glob
))
3210 if (!context_globAccess (sr
))
3216 message ("Called procedure %s may access %s %q",
3217 exprNode_unparse (e
),
3218 sRef_unparseScope (sr
),
3219 uentry_getName (glob
)),
3226 message ("Undocumented use of %s %s",
3227 sRef_unparseScope (sr
),
3228 exprNode_unparse (e
)),
3237 llbug (message ("Global not variable: %q", uentry_unparse (glob
)));
3242 reflectEnsuresClause (exprNode ret
, uentry le
, exprNode f
, exprNodeList args
)
3244 DPRINTF (("Reflect ensures clause: %s(%s) / %s / %s",
3245 exprNode_unparse (f
), exprNodeList_unparse (args
),
3246 uentry_unparseFull (le
),
3247 stateClauseList_unparse (uentry_getStateClauseList (le
))));
3249 if (uentry_isValid (le
) && uentry_isFunction (le
))
3251 stateClauseList sclauses
= uentry_getStateClauseList (le
);
3253 if (stateClauseList_isDefined (sclauses
))
3255 DPRINTF (("Reflect ensures: %s / %s / %s",
3256 uentry_unparse (le
),
3257 exprNode_unparse (f
), exprNodeList_unparse (args
)));
3259 stateClauseList_elements (sclauses
, cl
)
3261 if (stateClause_hasEnsures (cl
))
3263 /* Same in usymtab.c:1904 */
3264 if (stateClause_setsMetaState (cl
))
3266 qual q
= stateClause_getMetaQual (cl
);
3267 annotationInfo ainfo
= qual_getAnnotationInfo (q
);
3268 metaStateInfo minfo
= annotationInfo_getState (ainfo
);
3269 cstring key
= metaStateInfo_getName (minfo
);
3270 int mvalue
= annotationInfo_getValue (ainfo
);
3272 sRefSet osrs
= sRefSet_undefined
;
3275 if (stateClause_isGlobal (cl
))
3277 srs
= sRefSet_single (usymtab_lookupGlobalMarker ());
3282 srs
= stateClause_getRefs (cl
);
3285 DPRINTF (("Reflect ensures clause: %s", stateClause_unparse (cl
)));
3288 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl
)));
3290 sRefSet_elements (srs
, sel
)
3294 if (sRef_isResult (sRef_getRootBase (sel
)))
3296 s
= exprNode_getSref (ret
);
3300 s
= sRef_fixBaseParam (sel
, args
);
3303 DPRINTF (("Reflecting state clause on: %s / %s",
3304 sRef_unparse (sel
), sRef_unparse (s
)));
3306 sRef_setMetaStateValueComplete (s
, key
, mvalue
, exprNode_loc (f
));
3307 } end_sRefSet_elements
;
3309 sRefSet_free (osrs
);
3313 sRefSet srs
= stateClause_getRefs (cl
);
3314 sRefModVal modf
= stateClause_getEnsuresFunction (cl
);
3315 int eparam
= stateClause_getStateParameter (cl
);
3317 llassert (modf
!= NULL
);
3319 DPRINTF (("Reflect after clause: %s / %s",
3320 stateClause_unparse (cl
),
3321 sRefSet_unparse (srs
)));
3323 sRefSet_elements (srs
, sel
)
3327 DPRINTF (("elements: %s", sRef_unparse (sel
)));
3328 DPRINTF (("elements: %s", sRef_unparseFull (sel
)));
3330 if (sRef_isResult (sRef_getRootBase (sel
)))
3332 DPRINTF (("Fix base: %s / %s",
3333 sRef_unparse (sel
), sRef_unparse (exprNode_getSref (ret
))));
3334 s
= sRef_fixBase (sel
, exprNode_getSref (ret
));
3335 DPRINTF (("==> %s", sRef_unparseFull (s
)));
3339 s
= sRef_fixBaseParam (sel
, args
);
3342 DPRINTF (("elements: %s", sRef_unparse (s
)));
3343 DPRINTF (("elements: %s", sRef_unparseFull (s
)));
3345 DPRINTF (("Reflecting state clause on: %s / %s",
3346 sRef_unparseFull (sel
), sRef_unparseFull (s
)));
3348 /* evans 2001-08-24 - added aliasSetCompleteParam */
3349 sRef_aliasSetCompleteParam (modf
, s
, eparam
, exprNode_loc (f
));
3351 DPRINTF (("After reflecting state clause on: %s / %s",
3352 sRef_unparseFull (sel
), sRef_unparseFull (s
)));
3353 } end_sRefSet_elements
;
3356 } end_stateClauseList_elements
;
3359 DPRINTF (("Here: %s / %s",
3360 uentry_unparseFull (le
),
3361 bool_unparse (uentry_hasMetaStateEnsures (le
))));
3363 if (uentry_hasMetaStateEnsures (le
))
3365 fileloc loc
= exprNode_loc (f
);
3367 metaStateConstraintList mscl
= uentry_getMetaStateEnsures (le
);
3369 metaStateConstraintList_elements (mscl
, msc
)
3371 metaStateSpecifier msspec
= metaStateConstraint_getSpecifier (msc
);
3372 metaStateInfo msinfo
= metaStateSpecifier_getMetaStateInfo (msspec
);
3373 metaStateExpression msexpr
= metaStateConstraint_getExpression (msc
);
3374 cstring key
= metaStateInfo_getName (msinfo
);
3375 sRef mlsr
= metaStateSpecifier_getSref (msspec
);
3377 sRef lastref
= sRef_undefined
;
3378 stateValue sval
= stateValue_undefined
;
3380 DPRINTF (("Meta state constraint for %s: %s", uentry_unparse (le
),
3381 metaStateConstraint_unparse (msc
)));
3382 DPRINTF (("Matches left: %s", sRef_unparseDebug (mlsr
)));
3384 if (sRef_isResult (sRef_getRootBase (mlsr
)))
3386 s
= exprNode_getSref (ret
);
3390 s
= sRef_fixBaseParam (mlsr
, args
);
3393 DPRINTF (("Setting state: %s", sRef_unparseFull (s
)));
3395 while (metaStateExpression_isDefined (msexpr
))
3397 metaStateSpecifier ms
= metaStateExpression_getSpecifier (msexpr
);
3398 metaStateInfo msi
= metaStateSpecifier_getMetaStateInfo (ms
);
3401 DPRINTF (("Check expression: %s", metaStateExpression_unparse (msexpr
)));
3403 if (metaStateExpression_isMerge (msexpr
))
3405 msexpr
= metaStateExpression_getRest (msexpr
);
3409 msexpr
= metaStateExpression_undefined
;
3412 if (metaStateInfo_isDefined (msi
))
3414 /* Must match lhs state */
3415 llassert (metaStateInfo_equal (msinfo
, msi
));
3418 if (metaStateSpecifier_isElipsis (ms
))
3421 ** For elipsis, we need to merge all the relevant elipsis parameters
3425 uentryList params
= uentry_getParams (le
);
3426 int paramno
= uentryList_size (params
) - 1;
3428 if (!uentry_isElipsisMarker (uentryList_getN (params
, paramno
)))
3432 message ("Ensures clauses uses ... for function without ... in parameter list: %q",
3433 uentry_getName (le
)),
3434 uentry_whereLast (le
));
3435 /*@innerbreak@*/ break;
3438 while (paramno
< exprNodeList_size (args
))
3440 exprNode arg
= exprNodeList_getN (args
, paramno
);
3441 fs
= exprNode_getSref (arg
);
3442 DPRINTF (("Merge arg: %s", exprNode_unparse (arg
)));
3444 /* cut and pasted... gack*/
3445 if (stateValue_isDefined (sval
))
3447 /* Use combination table to merge old state value with new one: */
3448 stateValue tval
= sRef_getMetaStateValue (fs
, key
);
3450 if (stateValue_isDefined (tval
))
3452 stateCombinationTable sctable
= metaStateInfo_getMergeTable (msinfo
);
3453 cstring msg
= cstring_undefined
;
3454 int nval
= stateCombinationTable_lookup (sctable
,
3455 stateValue_getValue (sval
),
3456 stateValue_getValue (tval
),
3458 DPRINTF (("Combining: %s + %s -> %d",
3459 stateValue_unparseValue (sval
, msinfo
),
3460 stateValue_unparseValue (tval
, msinfo
),
3463 if (nval
== stateValue_error
)
3468 ("Attributes merged in ensures clause in states that "
3469 "cannot be combined (%q is %q, %q is %q)%q",
3470 sRef_unparse (lastref
),
3471 stateValue_unparseValue (sval
, msinfo
),
3473 stateValue_unparseValue (tval
, msinfo
),
3474 cstring_isDefined (msg
) ?
3475 message (": %s", msg
) : cstring_undefined
),
3478 sRef_showMetaStateInfo (fs
, key
);
3482 stateValue_updateValueLoc (sval
, nval
, fileloc_undefined
);
3483 loc
= exprNode_loc (arg
);
3487 DPRINTF (("No value for: %s:%s", sRef_unparse (fs
), key
));
3492 sval
= sRef_getMetaStateValue (fs
, key
);
3497 if (stateValue_isError (sval
))
3499 /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3508 msr
= metaStateSpecifier_getSref (ms
);
3511 llassert (sRef_isParam (sRef_getRootBase (msr
)));
3512 fs
= sRef_fixBaseParam (msr
, args
);
3514 if (stateValue_isDefined (sval
))
3516 /* Use combination table to merge old state value with new one: */
3517 stateValue tval
= sRef_getMetaStateValue (fs
, key
);
3519 if (stateValue_isDefined (tval
))
3521 stateCombinationTable sctable
= metaStateInfo_getMergeTable (msinfo
);
3522 cstring msg
= cstring_undefined
;
3523 int nval
= stateCombinationTable_lookup (sctable
,
3524 stateValue_getValue (sval
),
3525 stateValue_getValue (tval
),
3527 DPRINTF (("Combining: %s + %s -> %d",
3528 stateValue_unparseValue (sval
, msinfo
),
3529 stateValue_unparseValue (tval
, msinfo
),
3532 if (nval
== stateValue_error
)
3537 ("Attributes merged in ensures clause in states that "
3538 "cannot be combined (%q is %q, %q is %q)%q",
3539 sRef_unparse (lastref
),
3540 stateValue_unparseValue (sval
, msinfo
),
3542 stateValue_unparseValue (tval
, msinfo
),
3543 cstring_isDefined (msg
)
3544 ? message (": %s", msg
) : cstring_undefined
),
3547 sRef_showMetaStateInfo (fs
, key
);
3551 stateValue_updateValueLoc (sval
, nval
, fileloc_undefined
);
3555 DPRINTF (("No value for: %s:%s", sRef_unparse (fs
), key
));
3560 sval
= sRef_getMetaStateValue (fs
, key
);
3565 if (stateValue_isError (sval
))
3567 /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3572 DPRINTF (("Setting: %s:%s <- %s", sRef_unparse (s
), key
, stateValue_unparse (sval
)));
3574 if (stateValue_isDefined (sval
))
3576 sRef_setMetaStateValueComplete (s
, key
, stateValue_getValue (sval
), loc
);
3580 DPRINTF (("Undefined state: %s", cstring_toCharsSafe (sRef_unparse (s
))));
3582 } end_metaStateConstraintList_elements
;
3584 metaStateConstraintList_free (mscl
);
3590 checkRequiresClause (uentry le
, exprNode f
, exprNodeList args
)
3592 DPRINTF (("Check requires clause: %s(%s) / %s / %s",
3593 exprNode_unparse (f
), exprNodeList_unparse (args
),
3594 uentry_unparseFull (le
),
3595 stateClauseList_unparse (uentry_getStateClauseList (le
))));
3597 if (uentry_isValid (le
) && uentry_isFunction (le
))
3599 stateClauseList sclauses
= uentry_getStateClauseList (le
);
3601 if (stateClauseList_isDefined (sclauses
))
3603 DPRINTF (("Check requires: %s / %s / %s",
3604 uentry_unparse (le
),
3605 exprNode_unparse (f
), exprNodeList_unparse (args
)));
3607 stateClauseList_elements (sclauses
, cl
)
3609 DPRINTF (("Check clause: %s / %s",
3610 stateClause_unparse (cl
),
3611 bool_unparse (stateClause_hasRequires (cl
))));
3613 if (stateClause_hasRequires (cl
))
3615 sRefSet osrs
= sRefSet_undefined
;
3618 if (stateClause_isGlobal (cl
))
3620 srs
= sRefSet_single (usymtab_lookupGlobalMarker ());
3625 srs
= stateClause_getRefs (cl
);
3628 DPRINTF (("Refs: %s", sRefSet_unparse (srs
)));
3630 if (stateClause_setsMetaState (cl
))
3632 qual q
= stateClause_getMetaQual (cl
);
3633 annotationInfo ainfo
= qual_getAnnotationInfo (q
);
3634 metaStateInfo minfo
= annotationInfo_getState (ainfo
);
3635 cstring key
= metaStateInfo_getName (minfo
);
3636 int mvalue
= annotationInfo_getValue (ainfo
);
3638 DPRINTF (("Requires meta state! %s = %d", key
, mvalue
));
3640 sRefSet_elements (srs
, sel
)
3642 sRef s
= sRef_fixBaseParam (sel
, args
);
3644 if (sRef_isResult (sRef_getRootBase (sel
)))
3650 DPRINTF (("Checking state clause on: %s / %s / %s = %d",
3651 sRef_unparseFull (sel
), sRef_unparseFull (s
),
3654 if (!sRef_checkMetaStateValue (s
, key
, mvalue
))
3656 DPRINTF (("HERE: %s", sRef_unparse (s
)));
3660 ("Requires clause of called function %q not satisfied%q (state is %q): %q",
3661 uentry_getName (le
),
3662 sRef_isGlobalMarker (s
)
3664 : message (" by %q", sRef_unparse (s
)),
3665 stateValue_unparseValue (sRef_getMetaStateValue (s
, key
),
3667 stateClause_unparse (cl
)),
3670 sRef_showAliasInfo (s
);
3674 DPRINTF (("Error supressed!"));
3675 DPRINTF (("Loc: %s", fileloc_unparse (exprNode_loc (f
))));
3676 DPRINTF (("Context supress: %s",
3677 bool_unparse (context_suppressFlagMsg (FLG_STATETRANSFER
, exprNode_loc (f
)))));
3681 } end_sRefSet_elements
;
3685 sRefModVal modf
= stateClause_getRequiresBodyFunction (cl
);
3686 int eparam
= stateClause_getStateParameter (cl
);
3688 DPRINTF (("Reflect after clause: %s / %s",
3689 stateClause_unparse (cl
),
3690 sRefSet_unparse (srs
)));
3692 llassert (modf
!= NULL
);
3694 sRefSet_elements (srs
, sel
)
3698 DPRINTF (("elements: %s", sRef_unparse (sel
)));
3699 DPRINTF (("elements: %s", sRef_unparseFull (sel
)));
3701 s
= sRef_fixBaseParam (sel
, args
);
3703 DPRINTF (("elements: %s", sRef_unparse (s
)));
3704 DPRINTF (("elements: %s", sRef_unparseFull (s
)));
3706 if (sRef_isResult (sRef_getRootBase (sel
)))
3708 ; /* what do we do about results? */
3712 DPRINTF (("Reflecting state clause on: %s / %s",
3713 sRef_unparse (sel
), sRef_unparse (s
)));
3715 modf (s
, eparam
, exprNode_loc (f
));
3717 } end_sRefSet_elements
;
3720 sRefSet_free (osrs
);
3722 } end_stateClauseList_elements
;
3727 static /*@only@*/ exprNode
3728 functionCallSafe (/*@only@*/ /*@notnull@*/ exprNode f
,
3729 ctype t
, /*@keep@*/ exprNodeList args
)
3731 /* requires f is a non-error exprNode, with type function */
3732 cstring fname
= exprNode_unparse (f
);
3733 uentry le
= exprNode_getUentry (f
);
3734 exprNode ret
= exprNode_createPartialCopy (f
);
3739 DPRINTF (("Call: %s %s",exprNode_unparse (f
), exprNodeList_unparse (args
)));
3741 ret
->typ
= ctype_getReturnType (t
);
3742 ret
->kind
= XPR_CALL
;
3744 ret
->edata
= exprData_makeCall (f
, args
);
3747 ** Order of these steps is very important!
3749 ** Must check for argument dependencies before messing up uses and sets.
3752 if (context_getFlag (FLG_EVALORDER
))
3754 exprNodeList_elements (args
, current
)
3756 if (exprNode_isDefined (current
))
3758 exprNode_addUse (current
, current
->sref
);
3760 } end_exprNodeList_elements
;
3762 if (context_maybeSet (FLG_EVALORDER
) || context_maybeSet (FLG_EVALORDERUNCON
))
3764 checkSequencing (f
, args
);
3767 exprNodeList_elements (args
, current
)
3769 if (exprNode_isDefined (current
) && sRef_isMeaningful (current
->sref
))
3771 exprNode_addUse (ret
, sRef_makeDerived (current
->sref
));
3773 } end_exprNodeList_elements
;
3776 special
= checkArgs (le
, f
, t
, args
, ret
);
3777 checkGlobMods (f
, le
, args
, ret
, special
);
3778 checkRequiresClause (le
, f
, args
);
3781 if (uentry_isValid (le
)
3782 && (uentry_isFunction (le
)
3783 || (uentry_isVariable (le
)
3784 && ctype_isFunction (uentry_getType (le
)))))
3786 exitkind exk
= uentry_getExitCode (le
);
3788 /* f->typ is already set to the return type */
3790 DPRINTF (("Function: %s", uentry_unparseFull (le
)));
3791 ret
->sref
= uentry_returnedRef (le
, args
, exprNode_loc (f
));
3792 DPRINTF (("Returned: %s / %s",
3793 uentry_unparseFull (le
),
3794 sRef_unparseFull (ret
->sref
)));
3796 if (uentry_isFunction (le
) && exprNodeList_size (args
) >= 1)
3798 qual nullPred
= uentry_nullPred (le
);
3800 if (qual_isTrueNull (nullPred
))
3802 exprNode arg
= exprNodeList_head (args
);
3804 if (exprNode_isDefined (arg
))
3806 ret
->guards
= guardSet_addFalseGuard (ret
->guards
, arg
->sref
);
3809 else if (qual_isFalseNull (nullPred
))
3811 exprNode arg
= exprNodeList_head (args
);
3813 if (exprNode_isDefined (arg
))
3815 ret
->guards
= guardSet_addTrueGuard (ret
->guards
, arg
->sref
);
3820 llassert (qual_isUnknown (nullPred
));
3824 if (exitkind_isConditionalExit (exk
))
3828 ** if (arg0) then { exit! } else { ; }
3830 ** if (arg0) then { ; } else { exit! }
3835 llassert (!exprNodeList_isEmpty (args
));
3836 firstArg
= exprNodeList_head (args
);
3838 if (exprNode_isDefined (firstArg
)
3839 && !guardSet_isEmpty (firstArg
->guards
))
3841 usymtab_trueBranch (guardSet_undefined
);
3842 usymtab_altBranch (guardSet_undefined
);
3844 if (exitkind_isTrueExit (exk
))
3846 usymtab_popBranches (firstArg
,
3847 exprNode_makeMustExit (),
3849 TRUE
, TRUEEXITCLAUSE
);
3853 usymtab_popBranches (firstArg
,
3855 exprNode_makeMustExit (),
3856 TRUE
, FALSEEXITCLAUSE
);
3860 ret
->exitCode
= XK_MAYEXIT
;
3862 else if (exitkind_mustExit (exk
))
3864 ret
->exitCode
= XK_MUSTEXIT
;
3866 else if (exitkind_couldExit (exk
))
3868 ret
->exitCode
= XK_MAYEXIT
;
3875 if (cstring_equalLit (fname
, "exit"))
3877 if (exprNodeList_size (args
) == 1)
3879 exprNode arg
= exprNodeList_head (args
);
3881 if (exprNode_isDefined (arg
) && exprNode_knownIntValue (arg
))
3883 long int val
= multiVal_forceInt (exprNode_getValue (arg
));
3890 ("Argument to exit has implementation defined behavior: %s",
3891 exprNode_unparse (arg
)),
3892 exprNode_loc (arg
));
3900 ret
->sref
= sRef_undefined
;
3901 exprNode_checkSetAny (ret
, uentry_rawName (le
));
3904 DPRINTF (("Before reflect: %s", sRef_unparseFull (ret
->sref
)));
3905 DPRINTF (("Reflect: %s", uentry_unparseFull (le
)));
3906 reflectEnsuresClause (ret
, le
, f
, args
);
3909 DPRINTF (("Here: %s", sRef_unparseFull (ret
->sref
)));
3914 ** this is yucky! should keep the uentry as part of exprNode!
3917 uentry
exprNode_getUentry (exprNode e
)
3919 if (exprNode_isError (e
))
3921 return uentry_undefined
;
3925 cstring s
= exprNode_rootVarName (e
);
3926 uentry ue
= usymtab_lookupSafe (s
);
3933 ** Returns true iff e1 and e2 are both exactly the same storage
3937 static bool exprNode_sameStorage (exprNode e1
, exprNode e2
)
3939 sRef s1
= exprNode_getSref (e1
);
3940 sRef s2
= exprNode_getSref (e2
);
3942 return (sRef_realSame (s1
, s2
));
3946 exprNode_makeInitBlock (lltok brace
, /*@only@*/ exprNodeList inits
)
3948 exprNode ret
= exprNode_createPlain (ctype_unknown
);
3950 ret
->kind
= XPR_INITBLOCK
;
3951 ret
->edata
= exprData_makeCall (exprNode_undefined
, inits
);
3952 ret
->loc
= fileloc_update (ret
->loc
, lltok_getLoc (brace
));
3958 exprNode_functionCall (/*@only@*/ exprNode f
, /*@only@*/ exprNodeList args
)
3963 usymtab_checkAllValid ();
3966 if (exprNode_isUndefined (f
))
3969 exprNodeList_free (args
);
3970 return exprNode_undefined
;
3973 t
= exprNode_getType (f
);
3975 if (sRef_isLocalVar (f
->sref
))
3977 exprNode_checkUse (f
, f
->sref
, f
->loc
);
3979 if (sRef_possiblyNull (f
->sref
))
3981 if (!usymtab_isGuarded (f
->sref
))
3983 if (optgenerror (FLG_NULLDEREF
,
3984 message ("Function call using %s pointer %q",
3985 sRef_nullMessage (f
->sref
),
3986 sRef_unparse (f
->sref
)),
3989 sRef_showNullInfo (f
->sref
);
3990 sRef_setNullError (f
->sref
);
3998 if (ctype_isRealFunction (t
))
4000 exprNode ret
= functionCallSafe (f
, t
, args
);
4004 else if (ctype_isUnknown (t
))
4006 exprNode ret
= exprNode_createPartialCopy (f
);
4012 exprNodeList_elements (args
, current
)
4014 if (exprNode_isDefined (current
))
4016 exprNode_checkUse (ret
, current
->sref
, ret
->loc
);
4019 ** also, anything derivable from current->sref may be used
4022 exprNode_addUse (ret
, sRef_makeDerived (current
->sref
));
4023 exprNode_mergeUSs (ret
, current
);
4025 } end_exprNodeList_elements
;
4027 ret
->edata
= exprData_makeCall (f
, args
);
4028 ret
->kind
= XPR_CALL
;
4030 tstring
= cstring_copy (exprNode_unparse (f
));
4032 cstring_markOwned (tstring
);
4033 exprNode_checkSetAny (ret
, tstring
);
4039 voptgenerror (FLG_TYPE
,
4040 message ("Call to non-function (type %t): %s", t
,
4041 exprNode_unparse (f
)),
4044 exprNodeList_free (args
);
4046 return (exprNode_makeError ());
4051 exprNode_fieldAccessAux (/*@only@*/ exprNode s
, /*@observer@*/ fileloc loc
,
4052 /*@only@*/ cstring f
)
4054 exprNode ret
= exprNode_createPartialCopy (s
);
4056 ret
->kind
= XPR_FACCESS
;
4058 if (exprNode_isError (s
))
4060 ret
->edata
= exprData_makeField (s
, f
);
4065 ctype t
= exprNode_getType (s
);
4066 ctype tr
= ctype_realType (t
);
4068 checkMacroParen (s
);
4070 ret
->edata
= exprData_makeField (s
, f
);
4072 if (ctype_isStructorUnion (tr
))
4074 uentry tf
= uentryList_lookupField (ctype_getFields (tr
), f
);
4076 if (uentry_isUndefined (tf
))
4078 voptgenerror (FLG_TYPE
,
4079 message ("Access non-existent field %s of %t: %s", f
, t
,
4080 exprNode_unparse (ret
)),
4082 /*! cstring_free (f); */ /* evans 2001-03-25 self-detect */
4087 uentry_setUsed (tf
, exprNode_loc (ret
));
4089 ret
->typ
= uentry_getType (tf
);
4090 checkSafeUse (ret
, s
->sref
);
4092 ret
->sref
= sRef_makeField (s
->sref
, uentry_rawName (tf
));
4093 /*!? exprNode_free (s); */ /* evans 2001-03-25 self-detect */
4097 else /* isStructorUnion */
4099 if (ctype_isRealAbstract (tr
))
4103 message ("Access field of abstract type (%t): %s.%s",
4104 t
, exprNode_unparse (s
), f
),
4106 ret
->typ
= ctype_unknown
;
4110 if (ctype_isKnown (tr
))
4115 ("Access field of non-struct or union (%t): %s.%s",
4116 t
, exprNode_unparse (s
), f
),
4119 ret
->typ
= ctype_unknown
;
4123 cstring sn
= cstring_copy (f
);
4125 checkSafeUse (ret
, s
->sref
);
4126 cstring_markOwned (sn
);
4127 ret
->sref
= sRef_makeField (s
->sref
, sn
);
4139 exprNode_fieldAccess (/*@only@*/ exprNode s
, /*@only@*/ lltok dot
,
4140 /*@only@*/ cstring f
)
4142 exprNode res
= exprNode_fieldAccessAux (s
, lltok_getLoc (dot
), f
);
4148 exprNode_addParens (/*@only@*/ lltok lpar
, /*@only@*/ exprNode e
)
4150 exprNode ret
= exprNode_createPartialCopy (e
);
4152 ret
->loc
= fileloc_update (ret
->loc
, lltok_getLoc (lpar
));
4153 ret
->kind
= XPR_PARENS
;
4154 ret
->edata
= exprData_makeUop (e
, lpar
);
4156 if (!exprNode_isError (e
))
4158 ret
->exitCode
= e
->exitCode
;
4159 ret
->canBreak
= e
->canBreak
;
4160 ret
->mustBreak
= e
->mustBreak
;
4161 ret
->isJumpPoint
= e
->isJumpPoint
;
4162 ret
->sref
= e
->sref
;
4169 exprNode_arrowAccessAux (/*@only@*/ exprNode s
, /*@observer@*/ fileloc loc
,
4170 /*@only@*/ cstring f
)
4172 exprNode ret
= exprNode_createPartialCopy (s
);
4174 ret
->edata
= exprData_makeField (s
, f
);
4175 ret
->kind
= XPR_ARROW
;
4177 if (exprNode_isError (s
))
4183 ctype t
= exprNode_getType (s
);
4184 ctype tr
= ctype_realType (t
);
4186 checkMacroParen (s
);
4188 (void) ctype_fixArrayPtr (tr
); /* REWRITE THIS */
4190 if (ctype_isRealPointer (tr
))
4192 ctype b
= ctype_realType (ctype_baseArrayPtr (tr
));
4194 if (ctype_isStructorUnion (b
))
4196 uentry fentry
= uentryList_lookupField (ctype_getFields (b
), f
);
4198 if (sRef_isKnown (s
->sref
) && sRef_possiblyNull (s
->sref
))
4200 if (!usymtab_isGuarded (s
->sref
) && !context_inProtectVars ())
4204 message ("Arrow access from %s pointer%q: %s",
4205 sRef_nullMessage (s
->sref
),
4206 sRef_unparsePreOpt (s
->sref
),
4207 exprNode_unparse (ret
)),
4210 sRef_showNullInfo (s
->sref
);
4211 sRef_setNullError (s
->sref
);
4216 if (uentry_isUndefined (fentry
))
4220 message ("Access non-existent field %s of %t: %s",
4221 f
, t
, exprNode_unparse (ret
)),
4223 ret
->typ
= ctype_unknown
;
4229 ** was safeUse: shouldn't be safe!
4232 ** rec must be defined,
4233 ** *rec must be allocated
4234 ** rec->field need only be defined it if is an rvalue
4237 uentry_setUsed (fentry
, exprNode_loc (ret
));
4238 ret
->typ
= uentry_getType (fentry
);
4240 exprNode_checkUse (ret
, s
->sref
, s
->loc
);
4242 /* exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc); */
4243 ret
->sref
= sRef_makeArrow (s
->sref
, uentry_rawName (fentry
));
4247 else /* Pointer to something that is not a struct or union*/
4249 if (ctype_isRealAbstract (tr
))
4251 ctype xrt
= ctype_forceRealType (tr
);
4255 message ("Arrow access field of abstract type (%t): %s->%s",
4256 t
, exprNode_unparse (s
), f
),
4260 ** Set the state correctly, as if the abstraction is broken.
4263 if (ctype_isRealPointer (xrt
) &&
4264 (b
= ctype_realType (ctype_baseArrayPtr (xrt
)),
4265 ctype_isStructorUnion (b
)))
4267 uentry fentry
= uentryList_lookupField (ctype_getFields (b
), f
);
4268 ret
->typ
= uentry_getType (fentry
);
4269 ret
->sref
= sRef_makeArrow (s
->sref
, uentry_rawName (fentry
));
4273 ret
->typ
= ctype_unknown
;
4274 ret
->sref
= sRef_undefined
;
4277 else /* not a struct, union or abstract */
4279 if (ctype_isUnknown (tr
)) {
4280 cstring sn
= cstring_copy (f
);
4282 DPRINTF (("Here: %s", exprNode_unparse (s
)));
4284 exprNode_checkUse (ret
, s
->sref
, s
->loc
);
4285 exprNode_checkUse (ret
, sRef_makePointer (s
->sref
), s
->loc
);
4287 cstring_markOwned (sn
);
4288 ret
->sref
= sRef_makeArrow (s
->sref
, sn
);
4290 ret
->kind
= XPR_ARROW
;
4295 message ("Arrow access field of non-struct or union "
4296 "pointer (%t): %s->%s",
4297 t
, exprNode_unparse (s
), f
),
4300 ret
->typ
= ctype_unknown
;
4301 ret
->sref
= sRef_undefined
;
4306 else /* its not a pointer */
4308 if (!ctype_isUnknown (tr
))
4312 message ("Arrow access of non-pointer (%t): %s->%s",
4313 t
, exprNode_unparse (s
), f
),
4316 ret
->typ
= ctype_unknown
;
4317 ret
->sref
= sRef_undefined
;
4321 cstring sn
= cstring_copy (f
);
4323 DPRINTF (("Here: %s", exprNode_unparse (s
)));
4325 exprNode_checkUse (ret
, s
->sref
, s
->loc
);
4326 exprNode_checkUse (ret
, sRef_makePointer (s
->sref
), s
->loc
);
4328 cstring_markOwned (sn
);
4329 ret
->sref
= sRef_makeArrow (s
->sref
, sn
);
4331 ret
->kind
= XPR_ARROW
;
4342 exprNode_arrowAccess (/*@only@*/ exprNode s
,
4343 /*@only@*/ lltok arrow
,
4344 /*@only@*/ cstring f
)
4346 exprNode res
= exprNode_arrowAccessAux (s
, lltok_getLoc (arrow
), f
);
4352 ** only postOp's in C: i++ and i--
4356 exprNode_postOp (/*@only@*/ exprNode e
, /*@only@*/ lltok op
)
4358 /* check modification also */
4359 /* cstring opname = lltok_unparse (op);*/
4361 exprNode ret
= exprNode_createPartialCopy (e
);
4363 ret
->loc
= fileloc_update (ret
->loc
, lltok_getLoc (op
));
4364 ret
->kind
= XPR_POSTOP
;
4365 ret
->edata
= exprData_makeUop (e
, op
);
4367 if (!exprNode_isDefined (e
))
4372 checkMacroParen (e
);
4374 exprNode_checkUse (ret
, e
->sref
, e
->loc
);
4375 exprNode_checkSet (ret
, e
->sref
);
4377 t
= exprNode_getType (e
);
4379 if (sRef_isUnsafe (e
->sref
))
4381 voptgenerror (FLG_MACROPARAMS
,
4382 message ("Operand of %s is macro parameter (non-functional): %s%s",
4383 lltok_unparse (op
), exprNode_unparse (e
), lltok_unparse (op
)),
4385 sRef_makeSafe (e
->sref
);
4386 sRef_makeSafe (ret
->sref
);
4389 if (ctype_isForceRealNumeric (&t
) || ctype_isRealAP (t
))
4395 if (ctype_isRealAbstract (t
))
4397 if (ctype_isRealNumAbstract (t
)) {
4398 ; /* Allow operations on numabstract types */
4402 message ("Operand of %s is abstract type (%t): %s",
4403 lltok_unparse (op
), t
, exprNode_unparse (e
)),
4411 message ("Operand of %s is non-numeric (%t): %s",
4412 lltok_unparse (op
), t
, exprNode_unparse (e
)),
4415 ret
->typ
= ctype_unknown
;
4418 /* if (ctype_isZero (t)) e->typ = ctype_int; */
4420 exprNode_checkModify (e
, ret
);
4422 /* added 7/11/2000 D.L */
4424 /* updateEnvironmentForPostOp (e); */
4426 /* start modifications */
4427 /* added by Seejo on 4/16/2000 */
4429 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4431 if ((sRef_isPossiblyNullTerminated (e
->sref
)) || (sRef_isNullTerminated(e
->sref
))) {
4433 ret
->sref
= sRef_copy (e
->sref
);
4436 if (lltok_getTok (op
) == INC_OP
) {
4437 if (sRef_getSize(e
->sref
) > 0) {
4439 sRef_setSize (ret
->sref
, sRef_getSize(e
->sref
) - 1);
4441 if (sRef_getLen(e
->sref
) == 1) { /* i.e. the first character is \0 */
4442 /* Assumption: there is only 1 \0 in the buffer */
4443 /* This will not be correct if there are 2 \0's in the buffer */
4444 sRef_setNotNullTerminatedState(ret
->sref
);
4445 sRef_resetLen(ret
->sref
);
4447 sRef_setNullTerminatedState(ret
->sref
);
4448 sRef_setLen (ret
->sref
, sRef_getLen(e
->sref
) - 1);
4450 if (sRef_isNullTerminated (ret
->sref
))
4451 printf ("ret->sref is Null Terminated\n");
4452 else if (sRef_isPossiblyNullTerminated (ret
->sref
))
4453 printf ("ret->sref is Possibly Null Terminated\n");
4454 else if (sRef_isNotNullTerminated (ret
->sref
))
4455 printf ("ret->sref is Not Null Terminated\n");
4462 if (lltok_getTok (op
) == DEC_OP
) {
4463 if (sRef_getSize(e
->sref
) >= 0) {
4464 sRef_setSize (ret
->sref
, sRef_getSize(e
->sref
) + 1);
4465 sRef_setLen (ret
->sref
, sRef_getLen(e
->sref
) + 1);
4469 /* end modifications */
4475 exprNode_preOp (/*@only@*/ exprNode e
, /*@only@*/ lltok op
)
4477 bool checkMod
= FALSE
;
4479 int opid
= lltok_getTok (op
);
4480 exprNode ret
= exprNode_createSemiCopy (e
);
4482 exprNode_copySets (ret
, e
);
4484 multiVal_free (ret
->val
);
4485 ret
->val
= multiVal_undefined
;
4486 ret
->loc
= fileloc_update (ret
->loc
, lltok_getLoc (op
));
4487 ret
->kind
= XPR_PREOP
;
4488 ret
->edata
= exprData_makeUop (e
, op
);
4490 if (exprNode_isError (e
))
4495 checkMacroParen (e
);
4497 te
= exprNode_getType (e
);
4498 tr
= ctype_realType (te
);
4500 if (opid
!= TAMPERSAND
)
4502 exprNode_checkUse (ret
, e
->sref
, e
->loc
);
4504 if (ctype_isRealAbstract (tr
)
4505 && (!(ctype_isRealBool (te
) && (opid
== TEXCL
))))
4507 if (ctype_isRealNumAbstract (tr
))
4509 ; /* no warning for numabstract types */
4513 if (optgenerror (FLG_ABSTRACT
,
4514 message ("Operand of %s is abstract type (%t): %s",
4515 lltok_unparse (op
), tr
,
4516 exprNode_unparse (ret
)),
4519 tr
= te
= ctype_unknown
;
4520 ret
->typ
= ctype_unknown
;
4521 sRef_setNullError (e
->sref
);
4530 case DEC_OP
: /* should also check modification! */
4531 if (sRef_isMacroParamRef (e
->sref
))
4535 message ("Operand of %s is macro parameter (non-functional): %s",
4536 lltok_unparse (op
), exprNode_unparse (ret
)),
4541 exprNode_checkSet (ret
, e
->sref
);
4544 if (ctype_isForceRealNumeric (&tr
) || ctype_isRealAP (tr
))
4549 if (context_msgStrictOps ())
4553 message ("Operand of %s is non-numeric (%t): %s",
4554 lltok_unparse (op
), te
, exprNode_unparse (ret
)),
4557 ret
->typ
= ctype_int
;
4560 /* start modifications */
4561 /* added by Seejo on 4/16/2000 */
4563 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4565 if ((sRef_isPossiblyNullTerminated (e
->sref
))
4566 || (sRef_isNullTerminated(e
->sref
))) {
4567 ret
->sref
= sRef_copy (e
->sref
);
4570 if (lltok_getTok (op
) == INC_OP
) {
4571 if (sRef_getSize(e
->sref
) > 0) {
4573 sRef_setSize (ret
->sref
, sRef_getSize(e
->sref
) - 1);
4575 if (sRef_getLen(e
->sref
) == 1) { /* i.e. the first character is \0 */
4576 /* Assumption: there is only 1 \0 in the buffer */
4577 /* This will not be correct if there are 2 \0's in the buffer */
4578 sRef_setNotNullTerminatedState(ret
->sref
);
4579 sRef_resetLen (ret
->sref
);
4581 sRef_setNullTerminatedState(ret
->sref
);
4582 sRef_setLen (ret
->sref
, sRef_getLen(e
->sref
) - 1);
4588 if (lltok_getTok (op
) == DEC_OP
) {
4589 if (sRef_getSize(e
->sref
) >= 0) {
4590 sRef_setSize (ret
->sref
, sRef_getSize(e
->sref
) + 1);
4591 sRef_setLen (ret
->sref
, sRef_getLen(e
->sref
) + 1);
4596 /* end modifications */
4603 if (ctype_isForceRealNumeric (&tr
))
4607 ret
->val
= multiVal_invert (exprNode_getValue (e
));
4611 ret
->val
= multiVal_copy (exprNode_getValue (e
));
4616 if (context_msgStrictOps ())
4620 message ("Operand of %s is non-numeric (%t): %s",
4621 lltok_unparse (op
), te
, exprNode_unparse (ret
)),
4625 ret
->typ
= ctype_int
;
4629 case TEXCL
: /* maybe this should be restricted */
4630 guardSet_flip (ret
->guards
);
4632 if (ctype_isRealBool (te
) || ctype_isUnknown (te
))
4638 if (ctype_isRealPointer (tr
))
4640 if (sRef_isKnown (e
->sref
))
4642 ret
->guards
= guardSet_addFalseGuard (ret
->guards
, e
->sref
);
4646 (FLG_BOOLOPS
, FLG_PTRNEGATE
,
4647 message ("Operand of %s is non-boolean (%t): %s",
4648 lltok_unparse (op
), te
, exprNode_unparse (ret
)),
4655 message ("Operand of %s is non-boolean (%t): %s",
4656 lltok_unparse (op
), te
, exprNode_unparse (ret
)),
4660 ret
->typ
= ctype_bool
;
4665 if (ctype_isForceRealInt (&tr
))
4670 if (context_msgStrictOps ())
4674 message ("Operand of %s is non-integer (%t): %s",
4675 lltok_unparse (op
), te
, exprNode_unparse (ret
)),
4679 if (ctype_isInt (e
->typ
))
4685 ret
->typ
= ctype_int
;
4691 ret
->typ
= ctype_makePointer (e
->typ
);
4693 if (sRef_isKnown (e
->sref
))
4695 ret
->sref
= sRef_makeAddress (e
->sref
);
4702 if (ctype_isAP (tr
))
4704 ret
->typ
= ctype_baseArrayPtr (e
->typ
);
4708 if (ctype_isKnown (te
))
4710 if (ctype_isFunction (te
))
4716 message ("Dereference of function type (%t): %s",
4717 te
, exprNode_unparse (ret
)),
4722 voptgenerror (FLG_TYPE
,
4723 message ("Dereference of non-pointer (%t): %s",
4724 te
, exprNode_unparse (ret
)),
4726 ret
->typ
= ctype_unknown
;
4731 ret
->typ
= ctype_unknown
;
4736 if (sRef_isKnown (e
->sref
))
4738 DPRINTF (("Checking possibly null: %s", sRef_unparseFull (e
->sref
)));
4740 if (sRef_possiblyNull (e
->sref
))
4742 DPRINTF (("Checking possibly null: %s", sRef_unparse (e
->sref
)));
4743 if (!usymtab_isGuarded (e
->sref
) && !context_inProtectVars ())
4747 message ("Dereference of %s pointer %q: %s",
4748 sRef_nullMessage (e
->sref
),
4749 sRef_unparse (e
->sref
),
4750 exprNode_unparse (ret
)),
4753 sRef_showNullInfo (e
->sref
);
4754 sRef_setNotNull (e
->sref
, e
->loc
); /* suppress future messages */
4759 ret
->sref
= sRef_makePointer (e
->sref
);
4764 llbug (message ("exprNode_preOp: unhandled op: %s", lltok_unparse (op
)));
4769 exprNode_checkModify (e
, ret
);
4776 ** any reason to disallow sizeof (abstract type) ?
4780 ** used by both sizeof
4784 ctype
sizeof_resultType (void)
4786 static ctype sizet
= ctype_unknown
;
4788 if (ctype_isUnknown (sizet
))
4790 if (usymtab_existsType (cstring_makeLiteralTemp ("size_t")))
4792 sizet
= uentry_getAbstractType (usymtab_lookup (cstring_makeLiteralTemp ("size_t")));
4796 sizet
= ctype_ulint
;
4803 exprNode_sizeofType (/*@only@*/ qtype qt
)
4805 exprNode ret
= exprNode_create (sizeof_resultType ());
4806 ctype ct
= qtype_getType (qt
);
4808 ret
->kind
= XPR_SIZEOFT
;
4809 ret
->edata
= exprData_makeSizeofType (qt
);
4811 voptgenerror (FLG_SIZEOFTYPE
,
4812 message ("Parameter to sizeof is type %s: %s",
4814 exprNode_unparse (ret
)),
4821 exprNode_alignofType (/*@only@*/ qtype qt
)
4823 exprNode ret
= exprNode_create (sizeof_resultType ());
4824 ctype ct
= qtype_getType (qt
);
4826 ret
->kind
= XPR_ALIGNOFT
;
4827 ret
->edata
= exprData_makeSizeofType (qt
);
4829 voptgenerror (FLG_SIZEOFTYPE
,
4830 message ("Parameter to alignof is type %s: %s",
4832 exprNode_unparse (ret
)),
4838 exprNode
exprNode_offsetof (qtype qt
, cstringList s
)
4840 exprNode ret
= exprNode_create (sizeof_resultType ());
4841 ctype ct
= qtype_getType (qt
);
4843 ret
->kind
= XPR_OFFSETOF
;
4844 ret
->edata
= exprData_makeOffsetof (qt
, s
);
4846 if (!ctype_isRealSU (ct
))
4848 voptgenerror (FLG_TYPE
,
4849 message ("First parameter to offsetof is not a "
4850 "struct or union type (type %s): %s",
4852 exprNode_unparse (ret
)),
4859 cstringList_elements (s
, el
) {
4863 if (ctype_isUndefined (lt
))
4867 else if (!ctype_isRealSU (lt
))
4869 voptgenerror (FLG_TYPE
,
4870 message ("Inner offsetof type is not a "
4871 "struct or union type (type %s before field %s): %s",
4872 ctype_unparse (lt
), el
,
4873 exprNode_unparse (ret
)),
4879 fields
= ctype_getFields (ctype_realType (lt
));
4880 fld
= uentryList_lookupField (fields
, el
);
4881 DPRINTF (("Try: %s / %s", ctype_unparse (lt
), el
));
4883 if (uentry_isUndefined (fld
))
4885 if (ctype_equal (lt
, ct
)) {
4886 voptgenerror (FLG_TYPE
,
4887 message ("Field %s in offsetof is not the "
4888 "name of a field of %s: %s",
4891 exprNode_unparse (ret
)),
4894 voptgenerror (FLG_TYPE
,
4895 message ("Deep field %s in offsetof is not the "
4896 "name of a field of %s: %s",
4899 exprNode_unparse (ret
)),
4905 lt
= uentry_getType (fld
);
4908 } end_cstringList_elements
;
4910 /* Should report error if its a bit field - behavior is undefined! */
4917 exprNode_sizeofExpr (/*@only@*/ exprNode e
)
4921 if (exprNode_isUndefined (e
))
4923 ret
= exprNode_createLoc (ctype_unknown
, fileloc_copy (g_currentloc
));
4924 ret
->edata
= exprData_makeSingle (e
);
4925 ret
->typ
= sizeof_resultType ();
4926 ret
->kind
= XPR_SIZEOF
;
4930 uentry u
= exprNode_getUentry (e
);
4932 ret
= exprNode_createPartialCopy (e
);
4933 ret
->edata
= exprData_makeSingle (e
);
4935 ret
->typ
= sizeof_resultType ();
4936 ret
->kind
= XPR_SIZEOF
;
4938 if (uentry_isValid (u
)
4939 && uentry_isRefParam (u
)
4940 && ctype_isRealArray (uentry_getType (u
)))
4943 (FLG_SIZEOFFORMALARRAY
,
4944 message ("Parameter to sizeof is an array-type function parameter: %s",
4945 exprNode_unparse (ret
)),
4951 ** sizeof (x) doesn't "really" use x
4958 exprNode_alignofExpr (/*@only@*/ exprNode e
)
4962 if (exprNode_isUndefined (e
))
4964 ret
= exprNode_createLoc (ctype_unknown
, fileloc_copy (g_currentloc
));
4968 ret
= exprNode_createPartialCopy (e
);
4971 ret
->edata
= exprData_makeSingle (e
);
4972 ret
->typ
= sizeof_resultType ();
4973 ret
->kind
= XPR_ALIGNOF
;
4976 ** sizeof (x) doesn't "really" use x
4983 exprNode_cast (/*@only@*/ lltok tok
, /*@only@*/ exprNode e
, /*@only@*/ qtype q
)
4989 if (exprNode_isError (e
))
4993 return exprNode_undefined
;
4996 checkMacroParen (e
);
4998 c
= qtype_getType (q
);
4999 t
= exprNode_getType (e
);
5001 ret
= exprNode_createPartialCopy (e
);
5003 ret
->loc
= fileloc_update (ret
->loc
, lltok_getLoc (tok
));
5005 ret
->kind
= XPR_CAST
;
5006 ret
->edata
= exprData_makeCast (tok
, e
, q
);
5008 ret
->sref
= sRef_copy (e
->sref
);
5010 DPRINTF (("Cast: -> %s", sRef_unparseFull (ret
->sref
)));
5012 if (!sRef_isConst (e
->sref
))
5014 usymtab_addForceMustAlias (ret
->sref
, e
->sref
);
5017 DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret
->sref
)));
5018 sRef_setTypeFull (ret
->sref
, c
);
5019 DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret
->sref
)));
5025 ** void * <-> abstract * (if FLG_ABSTVOIDP)
5026 ** abstract * <-> void * (if FLG_ABSTVOIDP)
5029 if (ctype_isVoid (c
)) /* cast to void is always okay --- discard value */
5031 /* evans 2002-07-19: added this warning */
5032 DPRINTF (("Checking: %s / %s", exprNode_unparse (ret
), sRef_unparseFull (ret
->sref
)));
5033 if (sRef_isFresh (ret
->sref
))
5037 message ("New fresh storage %q(type %s) cast to void (not released): %s",
5038 sRef_unparseOpt (ret
->sref
),
5039 ctype_unparse (exprNode_getType (ret
)),
5040 exprNode_unparse (ret
)),
5041 exprNode_loc (ret
));
5044 else if (ctype_isRealAP (c
)) /* casting to array or pointer */
5046 ctype bc
= ctype_getBaseType (c
);
5047 ctype bt
= ctype_getBaseType (t
);
5048 ctype rt
= ctype_realType (t
);
5050 if (ctype_isFunction (ctype_baseArrayPtr (ctype_realType (c
)))
5051 && (ctype_isArrayPtr (rt
)
5052 && !ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt
)))))
5056 message ("Cast from function pointer type (%t) to "
5057 "non-function pointer (%t): %s",
5058 c
, t
, exprNode_unparse (ret
)),
5062 if (!ctype_isFunction (ctype_baseArrayPtr (c
))
5063 && (ctype_isArrayPtr (rt
)
5064 && ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt
)))))
5068 message ("Cast from non-function pointer type (%t) to "
5069 "function pointer (%t): %s",
5070 c
, t
, exprNode_unparse (ret
)),
5074 if (exprNode_isZero (e
) && context_getFlag (FLG_ZEROPTR
) &&
5075 !(ctype_isRealAbstract (bc
)
5076 && context_hasAccess (ctype_typeId (bc
))))
5078 ; /* okay to cast zero */
5082 if (ctype_isRealAbstract (bc
)
5083 && !context_hasAccess (ctype_typeId (bc
)))
5085 if (ctype_isVoidPointer (t
) || ctype_isUnknown (t
))
5089 message ("Cast to underlying abstract type %t: %s",
5090 c
, exprNode_unparse (ret
)),
5097 message ("Cast to underlying abstract type %t: %s",
5098 c
, exprNode_unparse (ret
)),
5103 if (ctype_isRealAbstract (bt
)
5104 && !context_hasAccess (ctype_typeId (bt
)))
5106 if (ctype_isUnknown (c
) || ctype_isVoidPointer (c
))
5110 message ("Cast from underlying abstract type %t: %s",
5111 t
, exprNode_unparse (ret
)),
5118 message ("Cast from underlying abstract type %t: %s",
5119 t
, exprNode_unparse (ret
)),
5127 ctype bt
= ctype_realType (ctype_getBaseType (t
));
5128 ctype bc
= ctype_realType (ctype_getBaseType (c
));
5130 if (ctype_isAbstract (bt
) && !context_hasAccess (ctype_typeId (bt
)))
5132 if (ctype_match (c
, t
))
5134 if (ctype_equal (c
, t
))
5138 message ("Redundant cast involving abstract type %t: %s",
5139 bt
, exprNode_unparse (ret
)),
5147 message ("Cast from abstract type %t: %s",
5148 bt
, exprNode_unparse (ret
)),
5153 if (ctype_isAbstract (bc
)
5154 && !context_hasAccess (ctype_typeId (bc
)))
5156 if (ctype_match (c
, t
))
5162 if (ctype_isNumAbstract (bc
))
5164 if (exprNode_isNumLiteral (e
))
5167 (FLG_NUMABSTRACTCAST
,
5168 message ("Cast from literal to numabstract type %t: %s", bc
,
5169 exprNode_unparse (ret
)),
5176 message ("Cast to numabstract type %t: %s", bc
,
5177 exprNode_unparse (ret
)),
5183 DPRINTF (("No access to: %s / %d",
5184 ctype_unparse (bc
), ctype_typeId (bc
)));
5185 DPRINTF (("Context %s %s",
5186 bool_unparse (context_inFunctionLike ()),
5187 context_unparse ()));
5190 message ("Cast to abstract type %t: %s", bc
,
5191 exprNode_unparse (ret
)),
5198 if (ctype_isAbstract (c
))
5200 if (sRef_isExposed (e
->sref
) || sRef_isOnly (e
->sref
))
5202 /* okay, cast exposed to abstract */
5203 sRef_clearExKindComplete (ret
->sref
, fileloc_undefined
);
5207 if (ctype_isVisiblySharable (t
)
5208 && sRef_isExternallyVisible (e
->sref
)
5209 && !(ctype_isAbstract (t
)
5210 && context_hasAccess (ctype_typeId (t
))))
5214 message ("Cast to abstract type from externally visible "
5215 "mutable storage exposes rep of %s: %s",
5217 exprNode_unparse (e
)),
5227 evaluationOrderUndefined (lltok op
)
5229 int opid
= lltok_getTok (op
);
5231 return (opid
!= AND_OP
&& opid
!= OR_OP
);
5234 static bool checkIntegral (/*@notnull@*/ exprNode e1
,
5235 /*@notnull@*/ exprNode e2
,
5236 /*@notnull@*/ exprNode ret
,
5241 ctype te1
= exprNode_getType (e1
);
5242 ctype te2
= exprNode_getType (e2
);
5244 ctype tr1
= ctype_realishType (te1
);
5245 ctype tr2
= ctype_realishType (te2
);
5247 if (ctype_isForceRealInt (&tr1
) && ctype_isForceRealInt (&tr2
))
5253 if (context_msgStrictOps ())
5255 if (!ctype_isInt (tr1
) && !ctype_isInt (tr2
))
5257 if (ctype_sameName (te1
, te2
))
5261 message ("Operands of %s are non-integer (%t): %s",
5262 lltok_unparse (op
), te1
,
5263 exprNode_unparse (ret
)),
5270 message ("Operands of %s are non-integers (%t, %t): %s",
5271 lltok_unparse (op
), te1
, te2
,
5272 exprNode_unparse (ret
)),
5276 else if (!ctype_isInt (tr1
))
5280 message ("Left operand of %s is non-integer (%t): %s",
5281 lltok_unparse (op
), te1
, exprNode_unparse (ret
)),
5285 /* !ctype_isInt (te2) */
5289 message ("Right operand of %s is non-integer (%t): %s",
5290 lltok_unparse (op
), te2
, exprNode_unparse (ret
)),
5300 ** returns exprNode representing e1 op e2
5302 ** uses msg if there are errors
5303 ** can be used for both assignment ops and regular ops
5308 static /*@only@*/ /*@notnull@*/ exprNode
5309 exprNode_makeOp (/*@keep@*/ exprNode e1
, /*@keep@*/ exprNode e2
,
5310 /*@keep@*/ lltok op
)
5312 ctype te1
, te2
, tr1
, tr2
, tret
;
5313 int opid
= lltok_getTok (op
);
5314 bool hasError
= FALSE
;
5317 if (exprNode_isError (e1
))
5319 ret
= exprNode_createPartialNVCopy (e2
);
5323 ret
= exprNode_createPartialNVCopy (e1
);
5326 ret
->val
= multiVal_undefined
;
5329 ret
->edata
= exprData_makeOp (e1
, e2
, op
);
5331 if (exprNode_isError (e1
) || exprNode_isError (e2
))
5333 if (opid
== TLT
|| opid
== TGT
|| opid
== LE_OP
|| opid
== GE_OP
5334 || opid
== EQ_OP
|| opid
== NE_OP
5335 || opid
== AND_OP
|| opid
== OR_OP
)
5337 ret
->typ
= ctype_bool
;
5340 if (exprNode_isDefined (e1
))
5342 exprNode_checkUse (ret
, e1
->sref
, e1
->loc
);
5345 if (exprNode_isDefined (e2
))
5347 exprNode_mergeUSs (ret
, e2
);
5348 exprNode_checkUse (ret
, e2
->sref
, e2
->loc
);
5354 tret
= ctype_unknown
;
5355 te1
= exprNode_getType (e1
);
5357 DPRINTF (("te1 = %s / %s", exprNode_unparse (e1
), ctype_unparse (te1
)));
5359 te2
= exprNode_getType (e2
);
5361 tr1
= ctype_realishType (te1
);
5362 tr2
= ctype_realishType (te2
);
5366 exprNode_produceGuards (e2
);
5367 ret
->guards
= guardSet_or (ret
->guards
, e2
->guards
);
5369 else if (opid
== AND_OP
)
5371 exprNode_produceGuards (e2
); /* evans 2003-08-13: need to produce guards for expression */
5372 /* Shouldn't this have already happened? */
5373 DPRINTF (("Anding guards: %s / %s", guardSet_unparse (ret
->guards
), guardSet_unparse (e2
->guards
)));
5374 ret
->guards
= guardSet_and (ret
->guards
, e2
->guards
);
5381 if (opid
== EQ_OP
|| opid
== NE_OP
)
5383 exprNode temp1
= e1
, temp2
= e2
;
5385 /* could do NULL == x */
5387 if (exprNode_isNullValue (e1
) || exprNode_isUnknownConstant (e1
))
5389 temp1
= e2
; temp2
= e1
;
5392 if (exprNode_isNullValue (temp2
) || exprNode_isUnknownConstant (temp2
))
5394 reflectNullTest (temp1
, (opid
== NE_OP
));
5395 guardSet_free (ret
->guards
);
5396 ret
->guards
= guardSet_copy (temp1
->guards
);
5400 if (opid
== TLT
|| opid
== TGT
|| opid
== LE_OP
|| opid
== GE_OP
5401 || opid
== EQ_OP
|| opid
== NE_OP
|| opid
== AND_OP
|| opid
== OR_OP
)
5406 if (anyAbstract (tr1
, tr2
) &&
5407 (!((ctype_isRealBool (te1
) || ctype_isRealBool (te2
)) &&
5408 (opid
== AND_OP
|| opid
== OR_OP
5409 || opid
== EQ_OP
|| opid
== NE_OP
))))
5411 if (abstractOpError (tr1
, tr2
, op
, e1
, e2
, e1
->loc
, e2
->loc
))
5413 tret
= ctype_unknown
;
5418 if (ctype_isUnknown (te1
) || ctype_isUnknown (te2
))
5420 /* unknown types, no comparisons possible */
5426 case TMULT
: /* multiplication and division: */
5428 case MUL_ASSIGN
: /* numeric, numeric -> numeric */
5429 case DIV_ASSIGN
: /* */
5430 if (opid
== TMULT
|| opid
== MUL_ASSIGN
)
5432 ret
->val
= multiVal_multiply (exprNode_getValue (e1
),
5433 exprNode_getValue (e2
));
5437 ret
->val
= multiVal_divide (exprNode_getValue (e1
),
5438 exprNode_getValue (e2
));
5441 tret
= checkNumerics (tr1
, tr2
, te1
, te2
, e1
, e2
, op
);
5444 case TPLUS
: /* addition and subtraction: */
5445 case TMINUS
: /* pointer, int -> pointer */
5446 case SUB_ASSIGN
: /* int, pointer -> pointer */
5447 case ADD_ASSIGN
: /* numeric, numeric -> numeric */
5448 if (opid
== TPLUS
|| opid
== ADD_ASSIGN
)
5450 ret
->val
= multiVal_add (exprNode_getValue (e1
),
5451 exprNode_getValue (e2
));
5455 ret
->val
= multiVal_subtract (exprNode_getValue (e1
),
5456 exprNode_getValue (e2
));
5459 tr1
= ctype_fixArrayPtr (tr1
);
5461 if ((ctype_isRealPointer (tr1
) && !exprNode_isNullValue (e1
))
5462 && (!ctype_isRealPointer (tr2
) && ctype_isRealInt (tr2
)))
5466 if (context_msgPointerArith ())
5470 message ("Pointer arithmetic (%t, %t): %s",
5471 te1
, te2
, exprNode_unparse (ret
)),
5476 ** Swap terms so e1 is always the pointer
5479 if (ctype_isRealPointer (tr1
))
5485 exprNode_swap (e1
, e2
);
5488 if (sRef_possiblyNull (e1
->sref
)
5489 && !usymtab_isGuarded (e1
->sref
))
5492 (FLG_NULLPOINTERARITH
,
5493 message ("Pointer arithmetic involving possibly "
5494 "null pointer %s: %s",
5495 exprNode_unparse (e1
),
5496 exprNode_unparse (ret
)),
5500 ret
->sref
= sRef_copy (e1
->sref
);
5502 /* start modifications */
5503 /* added by Seejo on 4/16/2000 */
5505 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5507 if ((sRef_isPossiblyNullTerminated (e1
->sref
)) || (sRef_isNullTerminated(e1
->sref
))) {
5510 added ugly fixed to stop
5511 program from crashing on point + int +int
5512 one day I'll fix this or ask Seejo wtf the codes supposed to do. */
5514 if (!multiVal_isInt (e2
->val
) )
5518 val
= (int) multiVal_forceInt (e2
->val
);
5520 /* Operator : + or += */
5521 if ((lltok_getTok (op
) == TPLUS
) || (lltok_getTok(op
) == ADD_ASSIGN
)) {
5522 if (sRef_getSize(e1
->sref
) >= val
) {/* Incrementing the pointer by
5523 val should not result in a
5524 size < 0 (size = 0 is ok !) */
5526 sRef_setSize (ret
->sref
, sRef_getSize(e1
->sref
) - val
);
5528 if (sRef_getLen(e1
->sref
) == val
) { /* i.e. the character at posn val is \0 */
5529 sRef_setNotNullTerminatedState(ret
->sref
);
5530 sRef_resetLen (ret
->sref
);
5532 sRef_setNullTerminatedState(ret
->sref
);
5533 sRef_setLen (ret
->sref
, sRef_getLen(e1
->sref
) - val
);
5538 /* Operator : - or -= */
5539 if ((lltok_getTok (op
) == TMINUS
) || (lltok_getTok (op
) == SUB_ASSIGN
)) {
5540 if (sRef_getSize(e1
->sref
) >= 0) {
5541 sRef_setSize (ret
->sref
, sRef_getSize(e1
->sref
) + val
);
5542 sRef_setLen (ret
->sref
, sRef_getLen(e1
->sref
) + val
);
5547 /* end modifications */
5549 sRef_setNullError (ret
->sref
);
5552 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5553 ** since is points to storage that should not be deallocated
5554 ** through this pointer.
5557 if (sRef_isOnly (ret
->sref
)
5558 || sRef_isFresh (ret
->sref
))
5560 sRef_setAliasKind (ret
->sref
, AK_DEPENDENT
, exprNode_loc (ret
));
5565 else if ((!ctype_isRealPointer(tr1
) && ctype_isRealInt (tr1
))
5566 && (ctype_isRealPointer (tr2
) && !exprNode_isNullValue (e2
)))
5568 if (context_msgPointerArith ())
5572 message ("Pointer arithmetic (%t, %t): %s",
5573 te1
, te2
, exprNode_unparse (ret
)),
5577 if (sRef_possiblyNull (e1
->sref
)
5578 && !usymtab_isGuarded (e1
->sref
))
5581 (FLG_NULLPOINTERARITH
,
5582 message ("Pointer arithmetic involving possibly "
5583 "null pointer %s: %s",
5584 exprNode_unparse (e2
),
5585 exprNode_unparse (ret
)),
5589 ret
->sref
= sRef_copy (e2
->sref
);
5591 /* start modifications */
5592 /* added by Seejo on 4/16/2000 */
5594 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5597 if ((sRef_isPossiblyNullTerminated (e2
->sref
)) || (sRef_isNullTerminated(e2
->sref
))) {
5598 if (multiVal_isDefined (e1
->val
))
5600 int val
= (int) multiVal_forceInt (e1
->val
);
5602 /* Operator : + or += */
5603 if ((lltok_getTok (op
) == TPLUS
) || (lltok_getTok(op
) == ADD_ASSIGN
)) {
5604 if (sRef_getSize(e2
->sref
) >= val
) {/* Incrementing the pointer by
5605 val should not result in a
5606 size < 0 (size = 0 is ok !) */
5608 sRef_setSize (ret
->sref
, sRef_getSize(e2
->sref
) - val
);
5610 if (sRef_getLen(e2
->sref
) == val
) { /* i.e. the character at posn val is \0 */
5611 sRef_setNotNullTerminatedState(ret
->sref
);
5612 sRef_resetLen (ret
->sref
);
5614 sRef_setNullTerminatedState(ret
->sref
);
5615 sRef_setLen (ret
->sref
, sRef_getLen(e2
->sref
) - val
);
5620 /* Operator : - or -= */
5621 if ((lltok_getTok (op
) == TMINUS
) || (lltok_getTok (op
) == SUB_ASSIGN
)) {
5622 if (sRef_getSize(e2
->sref
) >= 0) {
5623 sRef_setSize (ret
->sref
, sRef_getSize(e2
->sref
) + val
);
5624 sRef_setLen (ret
->sref
, sRef_getLen(e2
->sref
) + val
);
5630 /* end modifications */
5632 sRef_setNullError (ret
->sref
);
5635 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5636 ** since is points to storage that should not be deallocated
5637 ** through this pointer.
5640 if (sRef_isOnly (ret
->sref
)
5641 || sRef_isFresh (ret
->sref
)) {
5642 sRef_setAliasKind (ret
->sref
, AK_DEPENDENT
, exprNode_loc (ret
));
5646 ret
->sref
= e2
->sref
;
5650 tret
= checkNumerics (tr1
, tr2
, te1
, te2
, e1
, e2
, op
);
5659 case TAMPERSAND
: /* bitwise & */
5661 case TCIRC
: /* ^ (XOR) */
5666 bool reported
= FALSE
;
5672 if (opid
== LEFT_OP
|| opid
== LEFT_ASSIGN
5673 || opid
== RIGHT_OP
|| opid
== RIGHT_ASSIGN
)
5676 ** evans 2002-01-01: fixed this to follow ISO 6.5.7.
5679 if (!ctype_isUnsigned (tr2
)
5680 && !exprNode_isNonNegative (e2
))
5682 reported
= optgenerror
5684 message ("Right operand of %s may be negative (%t): %s",
5685 lltok_unparse (op
), te2
,
5686 exprNode_unparse (ret
)),
5690 if (!ctype_isUnsigned (tr1
)
5691 && !exprNode_isNonNegative (e1
))
5693 reported
= optgenerror
5694 (FLG_SHIFTIMPLEMENTATION
,
5695 message ("Left operand of %s may be negative (%t): %s",
5696 lltok_unparse (op
), te1
,
5697 exprNode_unparse (ret
)),
5702 ** Should check size of right operand also...
5708 if (!ctype_isUnsigned (tr1
))
5710 if (exprNode_isNonNegative (e1
)) {
5713 reported
= optgenerror
5715 message ("Left operand of %s is not unsigned value (%t): %s",
5716 lltok_unparse (op
), te1
,
5717 exprNode_unparse (ret
)),
5727 if (!ctype_isUnsigned (tr2
))
5729 if (!exprNode_isNonNegative (e2
)) {
5730 reported
= optgenerror
5732 message ("Right operand of %s is not unsigned value (%t): %s",
5733 lltok_unparse (op
), te2
,
5734 exprNode_unparse (ret
)),
5743 if (!checkIntegral (e1
, e2
, ret
, op
)) {
5744 te1
= ctype_unknown
;
5748 DPRINTF (("Set: %s", ctype_unparse (te1
)));
5751 ** tret is the widest type of te1 and te2
5754 tret
= ctype_widest (te1
, te2
);
5759 if (checkIntegral (e1
, e2
, ret
, op
)) {
5762 tret
= ctype_unknown
;
5767 case TLT
: /* comparisons */
5768 case TGT
: /* numeric, numeric -> bool */
5770 DPRINTF (("Here we go: %s / %s",
5771 ctype_unparse (tr1
), ctype_unparse (tr2
)));
5773 if ((ctype_isReal (tr1
) && !ctype_isInt (tr1
))
5774 || (ctype_isReal (tr2
) && !ctype_isInt (tr2
)))
5777 bool fepsilon
= FALSE
;
5779 if (!ctype_isReal (rtype
) || ctype_isInt (rtype
))
5784 if (opid
== TLT
|| opid
== TGT
)
5786 uentry ue1
= exprNode_getUentry (e1
);
5787 uentry ue2
= exprNode_getUentry (e2
);
5790 ** FLT_EPSILON, etc. really is a variable, not
5794 if (uentry_isVariable (ue1
))
5796 cstring uname
= uentry_rawName (ue1
);
5798 if (cstring_equalLit (uname
, "FLT_EPSILON")
5799 || cstring_equalLit (uname
, "DBL_EPSILON")
5800 || cstring_equalLit (uname
, "LDBL_EPSILON"))
5806 if (uentry_isVariable (ue2
))
5808 cstring uname
= uentry_rawName (ue2
);
5810 if (cstring_equalLit (uname
, "FLT_EPSILON")
5811 || cstring_equalLit (uname
, "DBL_EPSILON")
5812 || cstring_equalLit (uname
, "LDBL_EPSILON"))
5821 ; /* Don't complain. */
5825 if (opid
== EQ_OP
|| opid
== NE_OP
)
5829 message ("Dangerous equality comparison involving %s types: %s",
5830 ctype_unparse (rtype
),
5831 exprNode_unparse (ret
)),
5837 (FLG_REALRELATECOMPARE
,
5838 message ("Possibly dangerous relational comparison involving %s types: %s",
5839 ctype_unparse (rtype
),
5840 exprNode_unparse (ret
)),
5850 ** Types should match.
5853 DPRINTF (("Match types: %s / %s", exprNode_unparse (e1
),
5854 exprNode_unparse (e2
)));
5856 if (!exprNode_matchTypes (e1
, e2
))
5858 hasError
= gentypeerror
5860 message ("Operands of %s have incompatible types (%t, %t): %s",
5861 lltok_unparse (op
), te1
, te2
, exprNode_unparse (ret
)),
5867 || (ctype_isForceRealNumeric (&tr1
)
5868 && ctype_isForceRealNumeric (&tr2
)) ||
5869 (ctype_isRealPointer (tr1
) && ctype_isRealPointer (tr2
)))
5875 if ((ctype_isRealNumeric (tr1
) && ctype_isRealPointer (tr2
)) ||
5876 (ctype_isRealPointer (tr1
) && ctype_isRealNumeric (tr2
)))
5880 message ("Comparison of pointer and numeric (%t, %t): %s",
5881 te1
, te2
, exprNode_unparse (ret
)),
5886 (void) checkNumerics (tr1
, tr2
, te1
, te2
, e1
, e2
, op
);
5891 /* certain comparisons on unsigned's and zero look suspicious */
5893 if (opid
== TLT
|| opid
== LE_OP
|| opid
== GE_OP
)
5895 if ((ctype_isUnsigned (tr1
) && exprNode_isZero (e2
))
5896 || (ctype_isUnsigned (tr2
) && exprNode_isZero (e1
)))
5899 (FLG_UNSIGNEDCOMPARE
,
5900 message ("Comparison of unsigned value involving zero: %s",
5901 exprNode_unparse (ret
)),
5906 /* EQ_OP should NOT be used with booleans (unless one is FALSE) */
5908 if ((opid
== EQ_OP
|| opid
== NE_OP
) &&
5909 ctype_isDirectBool (tr1
) && ctype_isDirectBool (tr2
))
5912 ** is one a variable?
5915 if (uentry_isVariable (exprNode_getUentry (e1
))
5916 || uentry_isVariable (exprNode_getUentry (e2
)))
5919 ** comparisons with FALSE are okay
5922 if (exprNode_isFalseConstant (e1
)
5923 || exprNode_isFalseConstant (e2
))
5932 ("Use of %q with %s variables (risks inconsistency because "
5933 "of multiple true values): %s",
5934 cstring_makeLiteral ((opid
== EQ_OP
) ? "==" : "!="),
5935 context_printBoolName (), exprNode_unparse (ret
)),
5942 case AND_OP
: /* bool, bool -> bool */
5944 if (ctype_isForceRealBool (&tr1
) && ctype_isForceRealBool (&tr2
))
5950 if (context_maybeSet (FLG_BOOLOPS
))
5952 if (!ctype_isRealBool (te1
) && !ctype_isRealBool (te2
))
5954 if (ctype_sameName (te1
, te2
))
5958 message ("Operands of %s are non-boolean (%t): %s",
5959 lltok_unparse (op
), te1
,
5960 exprNode_unparse (ret
)),
5968 ("Operands of %s are non-booleans (%t, %t): %s",
5969 lltok_unparse (op
), te1
, te2
, exprNode_unparse (ret
)),
5973 else if (!ctype_isRealBool (te1
))
5977 message ("Left operand of %s is non-boolean (%t): %s",
5978 lltok_unparse (op
), te1
, exprNode_unparse (ret
)),
5981 else if (!ctype_isRealBool (te2
))
5985 message ("Right operand of %s is non-boolean (%t): %s",
5986 lltok_unparse (op
), te2
, exprNode_unparse (ret
)),
5999 (cstring_makeLiteral
6000 ("There has been a problem in the parser. This is believed to result "
6001 "from a problem with bison v. 1.25. Please try rebuidling Splint "
6002 "using the pre-compiled grammar files by commenting out the "
6003 "BISON= line in the top-level Makefile."));
6008 DPRINTF (("Return type %s: %s", exprNode_unparse (ret
), ctype_unparse (tret
)));
6010 exprNode_checkUse (ret
, e1
->sref
, e1
->loc
);
6011 exprNode_mergeUSs (ret
, e2
);
6012 exprNode_checkUse (ret
, e2
->sref
, e2
->loc
);
6018 exprNode_op (/*@only@*/ exprNode e1
, /*@keep@*/ exprNode e2
,
6019 /*@only@*/ lltok op
)
6023 checkMacroParen (e1
);
6024 checkMacroParen (e2
);
6026 if (evaluationOrderUndefined (op
) && context_maybeSet (FLG_EVALORDER
))
6028 checkExpressionDefined (e1
, e2
, op
);
6031 ret
= exprNode_makeOp (e1
, e2
, op
);
6036 void exprNode_checkAssignMod (exprNode e1
, exprNode ret
)
6039 ** This is somewhat bogus!
6041 ** Assigning to a nested observer in a non-observer datatype
6042 ** should not produce an error.
6045 sRef ref
= exprNode_getSref (e1
);
6047 DPRINTF (("Check assign mod: %s",
6048 sRef_unparseFull (ref
)));
6050 if (sRef_isObserver (ref
)
6051 || ((sRef_isFileStatic (ref
) || sRef_isFileOrGlobalScope (ref
))
6052 && ctype_isArray (ctype_realType (sRef_getType (ref
)))))
6054 sRef base
= sRef_getBase (ref
);
6056 if (sRef_isValid (base
) && sRef_isObserver (base
))
6058 exprNode_checkModify (e1
, ret
);
6062 exprNode_checkModifyVal (e1
, ret
);
6067 exprNode_checkModify (e1
, ret
);
6072 exprNode_assign (/*@only@*/ exprNode e1
, /*@only@*/ exprNode e2
, /*@only@*/ lltok op
)
6074 bool isalloc
= FALSE
;
6075 bool isjustalloc
= FALSE
;
6076 bool noalias
= FALSE
;
6079 DPRINTF (("%s [%s] <- %s [%s]",
6080 exprNode_unparse (e1
),
6081 ctype_unparse (e1
->typ
),
6082 exprNode_unparse (e2
),
6083 ctype_unparse (e2
->typ
)));
6085 if (lltok_getTok (op
) != TASSIGN
)
6087 ret
= exprNode_makeOp (e1
, e2
, op
);
6089 DPRINTF (("Here goes: %s %s",
6090 ctype_unparse (e1
->typ
),
6091 ctype_unparse (e2
->typ
)));
6093 if (exprNode_isDefined (e1
)
6094 && exprNode_isDefined (e2
))
6096 if (ctype_isNumeric (e2
->typ
)
6097 || ctype_isNumeric (e1
->typ
))
6099 /* Its a pointer arithmetic expression like ptr += i */
6106 ret
= exprNode_createPartialCopy (e1
);
6107 ret
->kind
= XPR_ASSIGN
;
6108 ret
->edata
= exprData_makeOp (e1
, e2
, op
);
6110 if (!exprNode_isError (e2
))
6112 ret
->sets
= sRefSet_union (ret
->sets
, e2
->sets
);
6113 ret
->msets
= sRefSet_union (ret
->msets
, e2
->msets
);
6114 ret
->uses
= sRefSet_union (ret
->uses
, e2
->uses
);
6118 checkExpressionDefined (e1
, e2
, op
);
6120 if (exprNode_isError (e1
))
6122 if (!exprNode_isError (e2
))
6124 ret
->loc
= fileloc_update (ret
->loc
, e2
->loc
);
6128 ret
->loc
= fileloc_update (ret
->loc
, g_currentloc
);
6132 if (!exprNode_isError (e2
))
6134 checkMacroParen (e2
);
6137 if (exprNode_isDefined (e1
))
6139 if (sRef_isMacroParamRef (e1
->sref
))
6141 if (context_inIterDef ())
6143 uentry ue
= sRef_getUentry (e1
->sref
);
6145 if (uentry_isYield (ue
))
6151 if (fileloc_isDefined (e1
->loc
))
6155 message ("Assignment to non-yield iter parameter: %q",
6156 sRef_unparse (e1
->sref
)),
6163 message ("Assignment to non-yield iter parameter: %q",
6164 sRef_unparse (e1
->sref
)),
6171 if (fileloc_isDefined (e1
->loc
))
6175 message ("Assignment to macro parameter: %q",
6176 sRef_unparse (e1
->sref
)),
6183 message ("Assignment to macro parameter: %q",
6184 sRef_unparse (e1
->sref
)),
6188 exprNode_checkAssignMod (e1
, ret
); /* evans 2001-07-22 */
6193 exprNode_checkAssignMod (e1
, ret
);
6196 if (exprNode_isDefined (e2
))
6198 if (lltok_getTok (op
) == TASSIGN
)
6200 ctype te1
= exprNode_getType (e1
);
6201 ctype te2
= exprNode_getType (e2
);
6203 if (ctype_isVoid (te2
))
6207 message ("Assignment of void value to %t: %s %s %s",
6208 te1
, exprNode_unparse (e1
),
6210 exprNode_unparse (e2
)),
6213 else if (!ctype_forceMatch (te1
, te2
))
6215 if (exprNode_matchLiteral (te1
, e2
))
6217 DPRINTF (("Literals match: %s / %s",
6218 ctype_unparse (te1
), exprNode_unparse (e2
)));
6219 if (ctype_isNumAbstract (te1
)) {
6220 if (!context_flagOn (FLG_NUMABSTRACTLIT
, e1
->loc
)) {
6221 (void) llgenhinterror
6224 ("Assignment of %t literal to numabstract type %t: %s %s %s",
6226 exprNode_unparse (e1
),
6228 exprNode_unparse (e2
)),
6230 ("Use +numabstractlit to allow numeric literals to be used as numabstract values"),
6239 message ("Assignment of %t to %t: %s %s %s",
6240 te2
, te1
, exprNode_unparse (e1
),
6242 exprNode_unparse (e2
)),
6248 /* Type checks okay */
6252 exprNode_mergeUSs (ret
, e2
);
6253 exprNode_checkUse (ret
, e2
->sref
, e2
->loc
);
6255 DPRINTF (("Do assign! %s %s", exprNode_unparse (e1
), exprNode_unparse (e2
)));
6262 doAssign (e1
, e2
, FALSE
);
6265 ret
->sref
= e1
->sref
;
6269 if (exprNode_isDefined (e2
))
6271 exprNode_mergeUSs (ret
, e2
);
6272 exprNode_checkUse (ret
, e2
->sref
, e2
->loc
);
6276 if (sRef_isPointer (e1
->sref
) && !sRef_isMacroParamRef (e1
->sref
))
6278 exprNode_checkUse (ret
, sRef_getBase (e1
->sref
), e1
->loc
);
6281 isjustalloc
= sRef_isJustAllocated (e1
->sref
);
6282 isalloc
= sRef_isAllocated (e1
->sref
);
6284 if (sRef_isField (e1
->sref
))
6286 sRef root
= sRef_getRootBase (sRef_getBase (e1
->sref
));
6288 if (!sRef_isAllocated (root
) && !sRef_isMacroParamRef (root
))
6290 exprNode_checkUse (ret
, root
, e1
->loc
);
6296 ** be careful! this defines e1->sref.
6299 /* evans 2001-07-22: removed if (!sRef_isMacroParamRef (e1->sref)) */
6301 DPRINTF (("Setting: %s -> %s", exprNode_unparse (ret
), sRef_unparse (e1
->sref
)));
6302 exprNode_checkSet (ret
, e1
->sref
);
6306 sRef_setAllocatedComplete (e1
->sref
, exprNode_isDefined (e2
)
6307 ? e2
->loc
: e1
->loc
);
6313 sRef_setAllocatedShallowComplete (e1
->sref
, exprNode_loc (e2
));
6322 exprNode_cond (/*@keep@*/ exprNode pred
, /*@keep@*/ exprNode ifclause
,
6323 /*@keep@*/ exprNode elseclause
)
6327 if (!exprNode_isError (pred
))
6329 ret
= exprNode_createPartialCopy (pred
);
6330 checkMacroParen (pred
);
6331 exprNode_checkPred (cstring_makeLiteralTemp ("conditional"), pred
);
6333 if (!exprNode_isError (ifclause
))
6335 checkMacroParen (ifclause
); /* update macro counts! */
6337 if (!exprNode_isError (elseclause
))
6339 checkMacroParen (elseclause
);
6341 if (!exprNode_matchTypes (ifclause
, elseclause
))
6344 (exprNode_getType (ifclause
),
6346 exprNode_getType (elseclause
),
6348 message ("Conditional clauses are not of same type: "
6350 exprNode_unparse (ifclause
),
6351 exprNode_getType (ifclause
),
6352 exprNode_unparse (elseclause
),
6353 exprNode_getType (elseclause
)),
6356 ret
->sref
= sRef_undefined
;
6357 ret
->typ
= ctype_unknown
;
6362 /* for now...should merge the states */
6363 ret
->sref
= ifclause
->sref
;
6364 ret
->typ
= ifclause
->typ
;
6366 if (exprNode_isNullValue (ifclause
))
6368 ret
->typ
= elseclause
->typ
;
6372 exprNode_checkUse (ret
, pred
->sref
, pred
->loc
);
6373 exprNode_checkUse (ifclause
, ifclause
->sref
, ifclause
->loc
);
6374 exprNode_checkUse (elseclause
, elseclause
->sref
, elseclause
->loc
);
6376 exprNode_mergeCondUSs (ret
, ifclause
, elseclause
);
6381 ret
->typ
= ifclause
->typ
;
6383 exprNode_checkUse (pred
, pred
->sref
, pred
->loc
);
6384 exprNode_checkUse (ifclause
, ifclause
->sref
, ifclause
->loc
);
6386 exprNode_mergeCondUSs (ret
, ifclause
, exprNode_undefined
);
6391 if (!exprNode_isError (elseclause
))
6393 ret
->typ
= elseclause
->typ
;
6395 exprNode_checkUse (pred
, pred
->sref
, pred
->loc
);
6396 exprNode_checkUse (elseclause
, elseclause
->sref
, elseclause
->loc
);
6398 exprNode_mergeCondUSs (ret
, exprNode_undefined
, elseclause
);
6402 else /* pred is error */
6404 if (!exprNode_isError (ifclause
))
6406 ret
= exprNode_createSemiCopy (ifclause
);
6408 checkMacroParen (ifclause
); /* update macro counts! */
6410 if (!exprNode_isError (elseclause
))
6412 checkMacroParen (elseclause
);
6414 ret
->typ
= ifclause
->typ
;
6416 if (!ctype_forceMatch (ifclause
->typ
, elseclause
->typ
))
6419 (exprNode_getType (ifclause
),
6421 exprNode_getType (elseclause
),
6423 message ("Conditional clauses are not of same type: "
6425 exprNode_unparse (ifclause
),
6426 exprNode_getType (ifclause
),
6427 exprNode_unparse (elseclause
),
6428 exprNode_getType (elseclause
)),
6431 ret
->typ
= ctype_unknown
;
6435 exprNode_checkUse (ifclause
, ifclause
->sref
, ifclause
->loc
);
6436 exprNode_checkUse (elseclause
, elseclause
->sref
, elseclause
->loc
);
6438 exprNode_mergeCondUSs (ret
, ifclause
, elseclause
);
6441 else if (!exprNode_isError (elseclause
)) /* pred, if errors */
6443 ret
= exprNode_createSemiCopy (ifclause
);
6445 ret
->typ
= elseclause
->typ
;
6446 checkMacroParen (elseclause
);
6448 exprNode_checkUse (elseclause
, elseclause
->sref
, elseclause
->loc
);
6449 exprNode_mergeCondUSs (ret
, exprNode_undefined
, elseclause
);
6451 else /* all errors! */
6453 ret
= exprNode_createLoc (ctype_unknown
, fileloc_copy (g_currentloc
));
6457 ret
->kind
= XPR_COND
;
6458 ret
->edata
= exprData_makeCond (pred
, ifclause
, elseclause
);
6460 if (exprNode_isDefined (ifclause
) && exprNode_isDefined (elseclause
))
6462 exprNode_combineControl (ret
, ifclause
, elseclause
);
6469 exprNode_condIfOmit (/*@keep@*/ exprNode pred
,
6470 /*@keep@*/ exprNode elseclause
)
6472 exprNode ifclause
= exprNode_createPartialCopy (pred
);
6474 if (!context_flagOn (FLG_GNUEXTENSIONS
, exprNode_loc (pred
)))
6476 (void) llgenhinterror
6478 message ("Conditionals with Omitted Operands is not supported by ISO C99"),
6479 message ("Use +gnuextensions to allow compound statement "
6480 "expressions (and other GNU language extensions) "
6481 "without this warning"),
6482 exprNode_loc (pred
));
6485 return exprNode_cond(pred
, ifclause
, elseclause
);
6489 exprNode_vaArg (/*@only@*/ lltok tok
, /*@only@*/ exprNode arg
, /*@only@*/ qtype qt
)
6491 ctype totype
= qtype_getType (qt
);
6493 exprNode_createPartialLocCopy (arg
, fileloc_copy (lltok_getLoc (tok
)));
6497 ** check use of va_arg : <valist>, type -> type
6500 if (exprNode_isError (arg
))
6505 targ
= exprNode_getType (arg
);
6508 ** arg should have be a pointer
6511 if (!ctype_isUA (targ
) ||
6512 (!typeId_equal (ctype_typeId (targ
),
6513 usymtab_getTypeId (cstring_makeLiteralTemp ("va_list")))))
6517 message ("First argument to va_arg is not a va_list (type %t): %s",
6518 targ
, exprNode_unparse (arg
)),
6522 exprNode_checkSet (ret
, arg
->sref
);
6526 ** return type is totype
6530 ret
->kind
= XPR_VAARG
;
6531 ret
->edata
= exprData_makeCast (tok
, arg
, qt
);
6536 exprNode
exprNode_labelMarker (/*@only@*/ cstring label
)
6538 exprNode ret
= exprNode_createPlain (ctype_undefined
);
6539 ret
->kind
= XPR_LABEL
;
6540 ret
->edata
= exprData_makeLiteral (label
);
6541 ret
->isJumpPoint
= TRUE
;
6543 return (ret
); /* for now, ignore label */
6546 exprNode
exprNode_notReached (/*@returned@*/ exprNode stmt
)
6548 if (exprNode_isDefined (stmt
))
6550 stmt
->isJumpPoint
= TRUE
;
6552 /* This prevent stray no return path errors, etc. */
6553 stmt
->exitCode
= XK_MUSTEXIT
;
6559 static bool exprNode_isDefaultMarker (exprNode e
)
6561 if (exprNode_isDefined (e
))
6563 return (e
->kind
== XPR_DEFAULT
|| e
->kind
== XPR_FTDEFAULT
);
6569 bool exprNode_isCaseMarker (exprNode e
)
6571 if (exprNode_isDefined (e
))
6573 return (e
->kind
== XPR_FTCASE
|| e
->kind
== XPR_CASE
);
6579 static bool exprNode_isLabelMarker (exprNode e
)
6581 if (exprNode_isDefined (e
))
6583 return (e
->kind
== XPR_LABEL
);
6589 exprNode
exprNode_caseMarker (/*@only@*/ exprNode test
, bool fallThrough
)
6591 exprNode ret
= exprNode_createPartialCopy (test
);
6593 ret
->kind
= fallThrough
? XPR_FTCASE
: XPR_CASE
;
6595 if (exprNode_isError (test
)) {
6599 exprNode_checkUse (ret
, test
->sref
, test
->loc
);
6601 usymtab_setExitCode (ret
->exitCode
);
6605 usymtab_setMustBreak ();
6608 ret
->edata
= exprData_makeSingle (test
);
6609 ret
->isJumpPoint
= TRUE
;
6615 exprNode
exprNode_caseStatement (/*@only@*/ exprNode test
, /*@only@*/ exprNode stmt
, bool fallThrough
)
6617 exprNode ret
= exprNode_createPartialCopy (test
);
6619 ret
->kind
= fallThrough
? XPR_FTCASE
: XPR_CASE
;
6620 ret
->edata
= exprData_makePair (test
, stmt
);
6621 ret
->isJumpPoint
= TRUE
;
6623 if (exprNode_isError (test
))
6628 exprNode_checkUse (ret
, test
->sref
, test
->loc
);
6630 if (exprNode_isError (stmt
))
6635 exprNode_mergeUSs (ret
, stmt
);
6637 ret
->exitCode
= stmt
->exitCode
;
6638 ret
->mustBreak
= stmt
->mustBreak
;
6639 ret
->canBreak
= stmt
->canBreak
;
6641 usymtab_setExitCode (ret
->exitCode
);
6645 usymtab_setMustBreak ();
6652 /*@notnull@*/ /*@only@*/ exprNode
6653 exprNode_defaultMarker (/*@only@*/ lltok def
, bool fallThrough
)
6655 exprNode ret
= exprNode_createTok (def
);
6657 ret
->isJumpPoint
= TRUE
;
6658 ret
->kind
= fallThrough
? XPR_FTDEFAULT
: XPR_DEFAULT
;
6663 exprNode_mayEscape (exprNode e
)
6665 if (exprNode_isDefined (e
))
6667 return exitkind_couldEscape (e
->exitCode
);
6673 exprNode_mustBreak (exprNode e
)
6675 if (exprNode_isDefined (e
))
6677 return e
->mustBreak
;
6684 exprNode_mustEscape (exprNode e
)
6686 if (exprNode_isDefined (e
))
6688 return exitkind_mustEscape (e
->exitCode
) || exprNode_mustBreak (e
);
6695 exprNode_errorEscape (exprNode e
)
6697 if (exprNode_isDefined (e
))
6699 return exitkind_isError (e
->exitCode
);
6705 exprNode
exprNode_concat (/*@only@*/ exprNode e1
, /*@only@*/ exprNode e2
)
6707 exprNode ret
= exprNode_createPartialCopy (e1
);
6709 DPRINTF (("Concat: %s / %s", exprNode_unparse (e1
), exprNode_unparse (e2
)));
6711 ret
->edata
= exprData_makePair (e1
, e2
);
6712 ret
->kind
= XPR_STMTLIST
;
6714 if (exprNode_isDefined (e1
))
6716 ret
->isJumpPoint
= e1
->isJumpPoint
;
6717 ret
->canBreak
= e1
->canBreak
;
6721 if (exprNode_isDefined (e2
))
6723 ret
->loc
= fileloc_update (ret
->loc
, e2
->loc
);
6727 if (exprNode_isDefined (e2
))
6729 ret
->exitCode
= e2
->exitCode
;
6730 ret
->mustBreak
= e2
->mustBreak
;
6731 if (e2
->canBreak
) ret
->canBreak
= TRUE
;
6735 ** if e1 must return, then e2 is unreachable!
6738 if (exprNode_isDefined (e1
) && exprNode_isDefined (e2
))
6740 if ((exprNode_mustEscape (e1
) || exprNode_mustBreak (e1
))
6741 && !(e2
->isJumpPoint
))
6743 if (context_getFlag (FLG_UNREACHABLE
))
6747 if (e2
->kind
== XPR_STMT
)
6749 nr
= exprData_getUopNode (e2
->edata
);
6752 if ((nr
->kind
== XPR_TOK
6753 && lltok_isSemi (exprData_getTok (nr
->edata
))))
6755 /* okay to have unreachable ";" */
6756 ret
->exitCode
= XK_MUSTEXIT
;
6757 ret
->canBreak
= TRUE
;
6761 if (optgenerror (FLG_UNREACHABLE
,
6762 message ("Unreachable code: %s",
6763 exprNode_unparseFirst (nr
)),
6766 ret
->isJumpPoint
= TRUE
;
6767 ret
->mustBreak
= FALSE
;
6768 ret
->exitCode
= XK_ERROR
;
6769 DPRINTF (("Jump point: %s", exprNode_unparse (ret
)));
6773 ret
->exitCode
= XK_MUSTEXIT
;
6774 ret
->canBreak
= TRUE
;
6782 if ((e2
->kind
== XPR_CASE
|| e2
->kind
== XPR_DEFAULT
))
6785 ** We want a warning anytime we have:
6787 ** yyy; <<<- no break or return
6791 exprNode lastStmt
= exprNode_lastStatement (e1
);
6793 if (exprNode_isDefined (lastStmt
)
6794 && !exprNode_mustEscape (lastStmt
)
6795 && !exprNode_mustBreak (lastStmt
)
6796 && !exprNode_isCaseMarker (lastStmt
)
6797 && !exprNode_isDefaultMarker (lastStmt
)
6798 && !exprNode_isLabelMarker (lastStmt
))
6800 voptgenerror (FLG_CASEBREAK
,
6802 ("Fall through case (no preceding break)"),
6809 exprNode_mergeUSs (ret
, e2
);
6811 usymtab_setExitCode (ret
->exitCode
);
6815 usymtab_setMustBreak ();
6818 DPRINTF (("==> %s", exprNode_unparse (ret
)));
6822 exprNode
exprNode_createTok (/*@only@*/ lltok t
)
6824 exprNode ret
= exprNode_create (ctype_unknown
);
6825 ret
->kind
= XPR_TOK
;
6826 ret
->edata
= exprData_makeTok (t
);
6830 exprNode
exprNode_statement (/*@only@*/ exprNode e
, /*@only@*/ lltok t
)
6832 if (!exprNode_isError (e
))
6834 exprChecks_checkStatementEffect(e
);
6837 return (exprNode_statementError (e
, t
));
6840 static exprNode
exprNode_statementError (/*@only@*/ exprNode e
, /*@only@*/ lltok t
)
6842 exprNode ret
= exprNode_createPartialCopy (e
);
6844 if (!exprNode_isError (e
))
6846 if (e
->kind
!= XPR_ASSIGN
)
6848 exprNode_checkUse (ret
, e
->sref
, e
->loc
);
6851 ret
->exitCode
= e
->exitCode
;
6852 ret
->canBreak
= e
->canBreak
;
6853 ret
->mustBreak
= e
->mustBreak
;
6856 ret
->edata
= exprData_makeUop (e
, t
);
6857 ret
->kind
= XPR_STMT
;
6862 exprNode
exprNode_checkExpr (/*@returned@*/ exprNode e
)
6864 if (!exprNode_isError (e
))
6866 if (e
->kind
!= XPR_ASSIGN
)
6868 exprNode_checkUse (e
, e
->sref
, e
->loc
);
6875 void exprNode_produceGuards (exprNode pred
)
6877 if (!exprNode_isError (pred
))
6879 if (ctype_isRealPointer (pred
->typ
))
6881 pred
->guards
= guardSet_addTrueGuard (pred
->guards
, pred
->sref
);
6884 exprNode_checkUse (pred
, pred
->sref
, pred
->loc
);
6885 exprNode_resetSref (pred
);
6889 exprNode
exprNode_compoundStatementExpression (/*@only@*/ lltok tlparen
, /*@only@*/ exprNode e
)
6893 DPRINTF (("Compound: %s", exprNode_unparse (e
)));
6895 if (!context_flagOn (FLG_GNUEXTENSIONS
, exprNode_loc (e
)))
6897 (void) llgenhinterror
6899 message ("Compound statement expressions is not supported by ISO C99"),
6900 message ("Use +gnuextensions to allow compound statement expressions (and other GNU language extensions) "
6901 "without this warning"),
6906 ** The type of a compoundStatementExpression is the type of the last statement
6909 llassert (exprNode_isBlock (e
));
6910 laststmt
= exprNode_lastStatement (e
);
6912 DPRINTF (("Last statement: %s / %s", exprNode_unparse (laststmt
), ctype_unparse (exprNode_getType (laststmt
))));
6913 DPRINTF (("e: %s", exprNode_unparse (e
)));
6914 e
->typ
= exprNode_getType (laststmt
);
6915 return exprNode_addParens (tlparen
, e
);
6919 exprNode
exprNode_makeBlock (/*@only@*/ exprNode e
)
6921 exprNode ret
= exprNode_createPartialCopy (e
);
6923 if (!exprNode_isError (e
))
6925 ret
->exitCode
= e
->exitCode
;
6926 ret
->canBreak
= e
->canBreak
;
6927 ret
->mustBreak
= e
->mustBreak
;
6930 DPRINTF (("Block e: %s", exprNode_unparse (e
)));
6931 ret
->edata
= exprData_makeSingle (e
);
6932 ret
->kind
= XPR_BLOCK
;
6933 DPRINTF (("Block: %s", exprNode_unparse (ret
)));
6937 static bool exprNode_isBlock (exprNode e
)
6939 return (exprNode_isDefined (e
)
6940 && ((e
)->kind
== XPR_BLOCK
));
6943 bool exprNode_isStatement (exprNode e
)
6945 return (exprNode_isDefined (e
)
6946 && ((e
)->kind
== XPR_STMT
));
6949 bool exprNode_isAssign (exprNode e
)
6951 if (exprNode_isDefined (e
))
6953 return (e
->kind
== XPR_ASSIGN
);
6959 bool exprNode_isEmptyStatement (exprNode e
)
6961 return (exprNode_isDefined (e
)
6962 && (e
->kind
== XPR_TOK
)
6963 && (lltok_isSemi (exprData_getTok (e
->edata
))));
6966 bool exprNode_isMultiStatement (exprNode e
)
6968 return (exprNode_isDefined (e
)
6969 && ((e
->kind
== XPR_FOR
)
6970 || (e
->kind
== XPR_FORPRED
)
6971 || (e
->kind
== XPR_IF
)
6972 || (e
->kind
== XPR_IFELSE
)
6973 || (e
->kind
== XPR_WHILE
)
6974 || (e
->kind
== XPR_WHILEPRED
)
6975 || (e
->kind
== XPR_DOWHILE
)
6976 || (e
->kind
== XPR_BLOCK
)
6977 || (e
->kind
== XPR_STMT
)
6978 || (e
->kind
== XPR_STMTLIST
)
6979 || (e
->kind
== XPR_SWITCH
)));
6982 void exprNode_checkIfPred (exprNode pred
)
6984 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred
);
6987 exprNode
exprNode_if (/*@only@*/ exprNode pred
, /*@only@*/ exprNode tclause
)
6990 bool emptyErr
= FALSE
;
6992 if (context_maybeSet (FLG_IFEMPTY
))
6994 if (exprNode_isEmptyStatement (tclause
))
6996 emptyErr
= optgenerror (FLG_IFEMPTY
,
6998 ("Body of if statement is empty"),
6999 exprNode_loc (tclause
));
7003 if (!emptyErr
&& context_maybeSet (FLG_IFBLOCK
))
7005 if (exprNode_isDefined (tclause
)
7006 && !exprNode_isBlock (tclause
))
7008 voptgenerror (FLG_IFBLOCK
,
7010 ("Body of if statement is not a block: %s",
7011 exprNode_unparse (tclause
)),
7012 exprNode_loc (tclause
));
7016 if (exprNode_isError (pred
))
7018 if (exprNode_isError (tclause
))
7020 ret
= exprNode_createLoc (ctype_unknown
, fileloc_copy (g_currentloc
));
7024 ret
= exprNode_createPartialCopy (tclause
);
7029 if (exprNode_mustEscape (pred
))
7033 message ("Predicate always exits: %s", exprNode_unparse (pred
)),
7034 exprNode_loc (pred
));
7037 exprNode_checkUse (pred
, pred
->sref
, pred
->loc
);
7039 if (!exprNode_isError (tclause
))
7041 exprNode_mergeCondUSs (pred
, tclause
, exprNode_undefined
);
7044 ret
= exprNode_createPartialCopy (pred
);
7048 ret
->edata
= exprData_makePair (pred
, tclause
);
7050 ret
->exitCode
= XK_UNKNOWN
;
7052 if (exprNode_isDefined (tclause
))
7054 ret
->exitCode
= exitkind_makeConditional (tclause
->exitCode
);
7055 ret
->canBreak
= tclause
->canBreak
;
7056 ret
->sets
= sRefSet_union (ret
->sets
, tclause
->sets
);
7057 ret
->msets
= sRefSet_union (ret
->msets
, tclause
->msets
);
7058 ret
->uses
= sRefSet_union (ret
->uses
, tclause
->uses
);
7061 ret
->mustBreak
= FALSE
;
7066 exprNode
exprNode_ifelse (/*@only@*/ exprNode pred
,
7067 /*@only@*/ exprNode tclause
,
7068 /*@only@*/ exprNode eclause
)
7071 bool tEmptyErr
= FALSE
;
7072 bool eEmptyErr
= FALSE
;
7074 if (context_maybeSet (FLG_IFEMPTY
))
7076 if (exprNode_isEmptyStatement (tclause
))
7078 tEmptyErr
= optgenerror
7081 ("Body of if clause of if statement is empty"),
7082 exprNode_loc (tclause
));
7085 if (exprNode_isEmptyStatement (eclause
))
7087 eEmptyErr
= optgenerror
7090 ("Body of else clause of if statement is empty"),
7091 exprNode_loc (eclause
));
7095 if (context_maybeSet (FLG_IFBLOCK
))
7098 && exprNode_isDefined (tclause
)
7099 && !exprNode_isBlock (tclause
))
7101 voptgenerror (FLG_IFBLOCK
,
7103 ("Body of if clause of if statement is not a block: %s",
7104 exprNode_unparse (tclause
)),
7105 exprNode_loc (tclause
));
7109 && exprNode_isDefined (eclause
)
7110 && !exprNode_isBlock (eclause
)
7111 && !(eclause
->kind
== XPR_IF
)
7112 && !(eclause
->kind
== XPR_IFELSE
))
7117 ("Body of else clause of if statement is not a block: %s",
7118 exprNode_unparse (eclause
)),
7119 exprNode_loc (eclause
));
7123 if (context_maybeSet (FLG_ELSEIFCOMPLETE
))
7125 if (exprNode_isDefined (eclause
)
7126 && (eclause
->kind
== XPR_IF
))
7128 voptgenerror (FLG_ELSEIFCOMPLETE
,
7129 message ("Incomplete else if logic (no final else): %s",
7130 exprNode_unparse (eclause
)),
7131 exprNode_loc (eclause
));
7135 if (exprNode_isError (pred
))
7137 if (exprNode_isError (tclause
))
7139 if (exprNode_isError (eclause
))
7141 ret
= exprNode_createLoc (ctype_unknown
, fileloc_copy (g_currentloc
));
7145 ret
= exprNode_createPartialCopy (eclause
);
7150 ret
= exprNode_createPartialCopy (tclause
);
7153 else /* pred is okay */
7155 ret
= exprNode_createPartialCopy (pred
);
7157 if (exprNode_mustEscape (pred
))
7161 message ("Predicate always exits: %s", exprNode_unparse (pred
)),
7162 exprNode_loc (pred
));
7165 exprNode_checkUse (ret
, pred
->sref
, pred
->loc
);
7166 exprNode_mergeCondUSs (ret
, tclause
, eclause
);
7169 ret
->kind
= XPR_IFELSE
;
7170 ret
->edata
= exprData_makeCond (pred
, tclause
, eclause
);
7172 if (exprNode_isDefined (tclause
) && exprNode_isDefined (eclause
))
7174 exprNode_combineControl (ret
, tclause
, eclause
);
7175 ret
->loc
= fileloc_update (ret
->loc
, eclause
->loc
);
7182 ** *allpaths <- TRUE iff all executions paths must go through the switch
7186 checkSwitchExpr (exprNode test
, /*@dependent@*/ exprNode e
, /*@out@*/ bool *allpaths
)
7188 exprNodeSList el
= exprNode_flatten (e
);
7189 bool mustReturn
= TRUE
; /* find a branch that doesn't */
7190 bool thisReturn
= FALSE
;
7191 bool hasDefault
= FALSE
;
7192 bool hasAllMembers
= FALSE
;
7193 bool inSwitch
= FALSE
;
7194 bool isEnumSwitch
= FALSE
;
7195 bool canBreak
= FALSE
;
7196 bool fallThrough
= FALSE
;
7197 ctype ct
= ctype_unknown
;
7198 enumNameSList usedEnums
;
7201 if (exprNode_isDefined (test
))
7206 ttype
= ctype_realType (ct
);
7208 if (ctype_isEnum (ttype
))
7210 isEnumSwitch
= TRUE
;
7211 enums
= ctype_elist (ttype
);
7212 usedEnums
= enumNameSList_new ();
7216 exprNodeSList_elements (el
, current
)
7219 DPRINTF ((message("checkSwitchExpr current = %s ", exprNode_unparse(current
) ) ));
7221 if (exprNode_isDefined (current
))
7223 switch (current
->kind
)
7230 (FLG_DUPLICATECASES
,
7231 message ("Duplicate default cases in switch"),
7232 exprNode_loc (current
));
7237 if (current
->kind
== XPR_DEFAULT
|| current
->kind
== XPR_FTDEFAULT
)
7245 exprNode st
= exprData_getSingle (current
->edata
);
7246 uentry ue
= exprNode_getUentry (st
);
7248 if (uentry_isValid (ue
))
7250 cstring cname
= uentry_rawName (ue
);
7252 if (enumNameList_member (/*@-usedef@*/enums
/*@=usedef@*/, cname
))
7254 if (enumNameSList_member
7255 (/*@-usedef@*/usedEnums
/*@=usedef@*/, cname
))
7258 (FLG_DUPLICATECASES
,
7259 message ("Duplicate case in switch: %s",
7265 enumNameSList_addh (usedEnums
, cname
);
7272 message ("Case in switch not %s member: %s",
7273 ctype_unparse (ct
), cname
),
7280 if (inSwitch
&& !fallThrough
)
7282 if (!thisReturn
|| canBreak
)
7292 /*@switchbreak@*/ break;
7294 thisReturn
= thisReturn
|| exprNode_mustEscape (current
);
7295 canBreak
= canBreak
|| current
->canBreak
;
7296 if (canBreak
) fallThrough
= FALSE
;
7299 } end_exprNodeSList_elements
;
7301 if (inSwitch
) /* check the last one! */
7303 if (!thisReturn
|| canBreak
)
7312 && (enumNameSList_size (/*@-usedef@*/usedEnums
/*@=usedef@*/) !=
7313 enumNameList_size (/*@-usedef@*/enums
/*@=usedef@*/)))
7315 enumNameSList unused
= enumNameSList_subtract (enums
, usedEnums
);
7317 voptgenerror (FLG_MISSCASE
,
7318 message ("Missing case%s in switch: %q",
7319 cstring_makeLiteralTemp
7320 ((enumNameSList_size (unused
) > 1) ? "s" : ""),
7321 enumNameSList_unparse (unused
)),
7324 enumNameSList_free (unused
);
7325 *allpaths
= FALSE
; /* evans 2002-01-01 */
7329 hasAllMembers
= TRUE
;
7333 enumNameSList_free (usedEnums
);
7337 *allpaths
= hasDefault
;
7340 exprNodeSList_free (el
);
7341 return ((hasDefault
|| hasAllMembers
) && mustReturn
);
7344 exprNode
exprNode_switch (/*@only@*/ exprNode e
, /*@only@*/ exprNode s
)
7346 exprNode ret
= exprNode_createPartialCopy (e
);
7349 DPRINTF (("Switch: %s", exprNode_unparse (s
)));
7351 ret
->kind
= XPR_SWITCH
;
7352 ret
->edata
= exprData_makePair (e
, s
);
7354 if (!exprNode_isError (s
))
7356 exprNode fs
= exprNode_firstStatement (s
);
7357 ret
->loc
= fileloc_update (ret
->loc
, s
->loc
);
7359 if (exprNode_isUndefined (fs
)
7360 || exprNode_isCaseMarker (fs
) || exprNode_isLabelMarker (fs
)
7361 || exprNode_isDefaultMarker (fs
)) {
7364 voptgenerror (FLG_FIRSTCASE
,
7366 ("Statement after switch is not a case: %s", exprNode_unparse (fs
)),
7371 if (!exprNode_isError (e
))
7373 if (checkSwitchExpr (e
, s
, &allpaths
))
7375 ret
->exitCode
= XK_MUSTRETURN
;
7379 ret
->exitCode
= e
->exitCode
;
7382 ret
->canBreak
= e
->canBreak
;
7383 ret
->mustBreak
= e
->mustBreak
;
7387 ** exprNode.c:3883,32: Variable allpaths used before definition
7394 DPRINTF (("Context exit switch!"));
7395 context_exitSwitch (ret
, allpaths
);
7396 DPRINTF (("Context exit switch done!"));
7401 static void checkInfiniteLoop (/*@notnull@*/ exprNode test
,
7402 /*@notnull@*/ exprNode body
)
7404 sRefSet tuses
= test
->uses
;
7406 if (!sRefSet_isEmpty (test
->uses
))
7408 sRefSet sets
= sRefSet_newCopy (body
->sets
);
7409 bool hasError
= TRUE
;
7410 bool innerState
= FALSE
;
7411 sRefSet tuncon
= sRefSet_undefined
;
7413 sets
= sRefSet_union (sets
, test
->sets
);
7414 sets
= sRefSet_union (sets
, body
->msets
);
7415 sets
= sRefSet_union (sets
, test
->msets
);
7417 sRefSet_allElements (tuses
, el
)
7419 if (sRef_isUnconstrained (el
))
7421 tuncon
= sRefSet_insert (tuncon
, el
);
7425 if (sRefSet_member (sets
, el
))
7432 if (sRef_isInternalState (el
)
7433 || sRef_isFileStatic (sRef_getRootBase (el
)))
7437 } end_sRefSet_allElements
;
7441 sRefSet suncon
= sRefSet_undefined
;
7442 bool sinner
= FALSE
;
7444 sRefSet_allElements (sets
, el
)
7446 if (sRef_isUnconstrained (el
))
7448 suncon
= sRefSet_insert (suncon
, el
);
7450 else if (sRef_isInternalState (el
))
7458 } end_sRefSet_allElements
;
7460 if (sinner
&& innerState
)
7464 else if (sRefSet_isEmpty (tuncon
)
7465 && sRefSet_isEmpty (suncon
))
7470 ("Suspected infinite loop. No value used in loop test (%q) "
7471 "is modified by test or loop body.",
7472 sRefSet_unparsePlain (tuses
)),
7477 if (sRefSet_isEmpty (tuncon
))
7481 message ("Suspected infinite loop. No condition values "
7482 "modified. Modification possible through "
7483 "unconstrained calls: %q",
7484 sRefSet_unparsePlain (suncon
)),
7491 message ("Suspected infinite loop. No condition values "
7492 "modified. Possible undetected dependency through "
7493 "unconstrained calls in loop test: %q",
7494 sRefSet_unparsePlain (tuncon
)),
7500 sRefSet_free (sets
);
7504 exprNode
exprNode_while (/*@keep@*/ exprNode t
, /*@keep@*/ exprNode b
)
7507 bool emptyErr
= FALSE
;
7509 if (context_maybeSet (FLG_WHILEEMPTY
))
7511 if (exprNode_isEmptyStatement (b
))
7513 emptyErr
= optgenerror
7516 ("Body of while statement is empty"),
7521 if (!emptyErr
&& context_maybeSet (FLG_WHILEBLOCK
))
7523 if (exprNode_isDefined (b
)
7524 && !exprNode_isBlock (b
))
7526 if (context_inIterDef ()
7527 && (b
->kind
== XPR_STMTLIST
7528 || b
->kind
== XPR_TOK
))
7534 voptgenerror (FLG_WHILEBLOCK
,
7536 ("Body of while statement is not a block: %s",
7537 exprNode_unparse (b
)),
7543 if (exprNode_isError (t
))
7545 if (exprNode_isError (b
))
7547 ret
= exprNode_createLoc (ctype_unknown
, fileloc_copy (g_currentloc
));
7551 ret
= exprNode_createPartialCopy (b
);
7558 ret
= exprNode_createPartialCopy (t
);
7560 llassert (t
->kind
== XPR_WHILEPRED
);
7562 test
= exprData_getSingle (t
->edata
);
7564 if (!exprNode_isError (b
) && exprNode_isDefined (test
))
7566 if (context_maybeSet (FLG_INFLOOPS
)
7567 || context_maybeSet (FLG_INFLOOPSUNCON
))
7570 ** check that some variable in the predicate is set by the body
7571 ** if the predicate uses any variables
7574 checkInfiniteLoop (test
, b
);
7577 exprNode_mergeUSs (ret
, b
);
7579 if (exprNode_isDefined (b
))
7581 ret
->exitCode
= exitkind_makeConditional (b
->exitCode
);
7586 ret
->edata
= exprData_makePair (t
, b
);
7587 ret
->kind
= XPR_WHILE
;
7589 if (exprNode_isDefined (t
) && exprNode_mustEscape (t
))
7593 message ("Predicate always exits: %s", exprNode_unparse (t
)),
7597 ret
->exitCode
= XK_NEVERESCAPE
;
7600 ** If loop is infinite, and there is no break inside,
7601 ** exit code is never reach.
7604 if (exprNode_knownIntValue (t
))
7606 if (!exprNode_isZero (t
))
7608 if (exprNode_isDefined (b
))
7612 /* Really, it means never reached. */
7613 ret
->exitCode
= XK_MUSTEXIT
;
7623 ret
->canBreak
= FALSE
;
7624 ret
->mustBreak
= FALSE
;
7630 ** do { b } while (t);
7632 ** note: body passed as first argument
7635 exprNode
exprNode_doWhile (/*@only@*/ exprNode b
, /*@only@*/ exprNode t
)
7639 DPRINTF (("Do while: %s / %s",
7640 exprNode_unparse (b
), exprNode_unparse (t
)));
7642 if (exprNode_isError (t
))
7644 if (exprNode_isError (b
))
7646 ret
= exprNode_createLoc (ctype_unknown
, fileloc_copy (g_currentloc
));
7650 ret
= exprNode_createPartialCopy (b
);
7652 ret
->exitCode
= exitkind_makeConditional (b
->exitCode
);
7653 exprNode_checkUse (ret
, b
->sref
, b
->loc
);
7654 ret
->exitCode
= b
->exitCode
;
7655 ret
->canBreak
= b
->canBreak
;
7656 ret
->mustBreak
= FALSE
;
7661 DPRINTF (("Do while: %s / %s",
7662 exitkind_unparse (t
->exitCode
),
7663 exitkind_unparse (b
->exitCode
)));
7665 ret
= exprNode_createPartialCopy (t
);
7666 exprNode_checkPred (cstring_makeLiteralTemp ("while"), t
);
7668 if (!exprNode_isError (b
))
7671 ** forgot the copy's --- why wasn't this detected??
7674 ret
->sets
= sRefSet_copyInto (ret
->sets
, b
->sets
);
7675 ret
->msets
= sRefSet_copyInto (ret
->msets
, b
->msets
);
7676 ret
->uses
= sRefSet_copyInto (ret
->uses
, b
->uses
);
7678 /* left this out --- causes and aliasing bug (infinite loop)
7679 should be detected?? */
7681 exprNode_checkUse (ret
, b
->sref
, b
->loc
);
7682 exprNode_mergeUSs (ret
, t
);
7683 exprNode_checkUse (ret
, t
->sref
, t
->loc
);
7685 /* evans 2001-10-05: while loop can break */
7686 ret
->exitCode
= exitkind_makeConditional (b
->exitCode
);
7688 DPRINTF (("Do while: %s",
7689 exitkind_unparse (ret
->exitCode
)));
7691 ret
->canBreak
= b
->canBreak
;
7693 /* Always FALSE for doWhile loops - break's when test is false */
7694 ret
->mustBreak
= FALSE
; /* b->mustBreak; */
7698 context_exitDoWhileClause (t
);
7700 ret
->kind
= XPR_DOWHILE
;
7701 ret
->edata
= exprData_makePair (t
, b
);
7705 bool exprNode_loopMustExec (exprNode forPred
)
7708 ** Returns true if it is obvious that the loop always executes at least once
7710 ** For now, we only identify the most obvious cases. Should be true anytime
7711 ** we can prove init => !test.
7714 if (exprNode_isDefined (forPred
))
7716 exprNode init
, test
;
7719 llassert (forPred
->kind
== XPR_FORPRED
);
7721 edata
= forPred
->edata
;
7722 init
= exprData_getTripleInit (edata
);
7723 test
= exprData_getTripleTest (edata
);
7725 if (exprNode_isAssign (init
))
7727 exprNode loopVar
= exprData_getOpA (init
->edata
);
7728 exprNode loopInit
= exprData_getOpB (init
->edata
);
7730 if (exprNode_isDefined (test
) && test
->kind
== XPR_OP
)
7732 exprNode testVar
= exprData_getOpA (test
->edata
);
7733 exprNode testVal
= exprData_getOpB (test
->edata
);
7734 lltok comp
= exprData_getOpTok (test
->edata
);
7735 int opid
= lltok_getTok (comp
);
7737 DPRINTF (("Same storage: %s / %s", exprNode_unparse (loopVar
),
7738 exprNode_unparse (testVar
)));
7740 if (exprNode_sameStorage (loopVar
, testVar
))
7742 multiVal valinit
= exprNode_getValue (loopInit
);
7743 multiVal valtest
= exprNode_getValue (testVal
);
7745 DPRINTF (("Values: %s / %s", multiVal_unparse (valinit
),
7746 multiVal_unparse (valtest
)));
7748 if (multiVal_isInt (valinit
) && multiVal_isInt (valtest
))
7750 long v1
= multiVal_forceInt (valinit
);
7751 long v2
= multiVal_forceInt (valtest
);
7753 DPRINTF (("Here: %ld %ld", v1
, v2
));
7755 if ((opid
== EQ_OP
&& v1
< v2
)
7756 || (opid
== NE_OP
&& v1
!= v2
)
7757 || (opid
== TLT
&& v1
<= v2
)
7758 || (opid
== TGT
&& v1
>= v2
)
7759 || (opid
== LE_OP
&& v1
< v2
)
7760 || (opid
== GE_OP
&& v1
> v2
))
7762 DPRINTF (("mustexec if inc"));
7771 DPRINTF (("loop must exec: FALSE"));
7775 exprNode
exprNode_for (/*@keep@*/ exprNode inc
, /*@keep@*/ exprNode body
)
7778 bool emptyErr
= FALSE
;
7780 if (context_maybeSet (FLG_FOREMPTY
))
7782 if (exprNode_isEmptyStatement (body
))
7784 emptyErr
= optgenerror
7787 ("Body of for statement is empty"),
7788 exprNode_loc (body
));
7792 if (!emptyErr
&& context_maybeSet (FLG_FORBLOCK
))
7794 if (exprNode_isDefined (body
)
7795 && !exprNode_isBlock (body
))
7797 if (context_inIterDef ()
7798 && (body
->kind
== XPR_STMTLIST
7799 || body
->kind
== XPR_TOK
))
7805 voptgenerror (FLG_FORBLOCK
,
7807 ("Body of for statement is not a block: %s",
7808 exprNode_unparse (body
)),
7809 exprNode_loc (body
));
7815 ** for ud purposes: (alreadly) init -> test -> (now) LOOP: body + inc + test
7818 if (exprNode_isError (body
))
7820 ret
= exprNode_createPartialCopy (inc
);
7824 ret
= exprNode_createPartialCopy (body
);
7826 ret
->exitCode
= exitkind_makeConditional (body
->exitCode
);
7828 exprNode_mergeUSs (inc
, body
);
7830 if (exprNode_isDefined (inc
))
7834 context_setMessageAnnote (cstring_makeLiteral ("in post loop increment"));
7836 tmp
= exprNode_effect (exprData_getTripleInc (inc
->edata
));
7837 exprNode_freeShallow (tmp
);
7839 context_clearMessageAnnote ();
7840 context_setMessageAnnote (cstring_makeLiteral ("in post loop test"));
7842 tmp
= exprNode_effect (exprData_getTripleTest (inc
->edata
));
7843 exprNode_freeShallow (tmp
);
7845 context_clearMessageAnnote ();
7847 ret
->uses
= sRefSet_copyInto (ret
->uses
, inc
->uses
);
7848 ret
->sets
= sRefSet_copyInto (ret
->sets
, inc
->sets
);
7849 ret
->msets
= sRefSet_copyInto (ret
->msets
, inc
->msets
);
7853 ret
->kind
= XPR_FOR
;
7854 ret
->edata
= exprData_makePair (inc
, body
);
7856 if (exprNode_isDefined (inc
)) {
7857 exprNode test
= exprData_getTripleTest (inc
->edata
);
7859 if (exprNode_isUndefined (test
)) {
7860 if (exprNode_isDefined (body
)) {
7861 if (!body
->canBreak
) {
7862 /* Really, it means never reached. */
7863 ret
->exitCode
= XK_MUSTEXIT
;
7873 ** for (init; test; inc)
7876 ** while (test) { body; inc; }
7878 ** Now: check use of init (may set vars for test)
7879 ** check use of test
7883 /*@observer@*/ guardSet
exprNode_getForGuards (exprNode pred
)
7887 if (exprNode_isError (pred
)) return guardSet_undefined
;
7889 llassert (pred
->kind
== XPR_FORPRED
);
7891 test
= exprData_getTripleTest (pred
->edata
);
7893 if (!exprNode_isError (test
))
7895 return (test
->guards
);
7898 return guardSet_undefined
;
7901 exprNode
exprNode_whilePred (/*@only@*/ exprNode test
)
7903 exprNode ret
= exprNode_createSemiCopy (test
);
7905 if (exprNode_isDefined (test
))
7907 exprNode_copySets (ret
, test
);
7908 exprNode_checkPred (cstring_makeLiteralTemp ("while"), test
);
7909 exprNode_checkUse (ret
, test
->sref
, test
->loc
);
7911 exprNode_produceGuards (test
);
7913 ret
->guards
= guardSet_copy (test
->guards
);
7916 ret
->edata
= exprData_makeSingle (test
);
7917 ret
->kind
= XPR_WHILEPRED
;
7921 exprNode
exprNode_forPred (/*@only@*/ exprNode init
, /*@only@*/ exprNode test
,
7922 /*@only@*/ exprNode inc
)
7927 ** for ud purposes: init -> test -> LOOP: [ body, inc ]
7930 exprNode_checkPred (cstring_makeLiteralTemp ("for"), test
);
7932 if (!exprNode_isError (inc
))
7934 ret
= exprNode_createPartialCopy (inc
);
7938 if (!exprNode_isError (init
))
7940 ret
= exprNode_createPartialCopy (init
);
7942 else if (!exprNode_isError (test
))
7944 ret
= exprNode_createPartialCopy (test
);
7948 ret
= exprNode_createUnknown ();
7952 exprNode_mergeUSs (ret
, init
);
7954 if (exprNode_isDefined (init
))
7956 exprNode_checkUse (ret
, init
->sref
, init
->loc
);
7959 exprNode_mergeUSs (ret
, test
);
7961 if (exprNode_isDefined (test
))
7963 exprNode_checkUse (ret
, test
->sref
, test
->loc
);
7966 ret
->kind
= XPR_FORPRED
;
7967 ret
->edata
= exprData_makeFor (init
, test
, inc
);
7971 /*@notnull@*/ /*@only@*/ exprNode
exprNode_goto (/*@only@*/ cstring label
)
7973 exprNode ret
= exprNode_createUnknown ();
7975 if (context_inMacro ())
7977 voptgenerror (FLG_MACROSTMT
,
7978 message ("Macro %s uses goto (not functional)",
7979 context_inFunctionName ()),
7983 ret
->kind
= XPR_GOTO
;
7984 ret
->edata
= exprData_makeLiteral (label
);
7985 ret
->mustBreak
= TRUE
;
7986 ret
->exitCode
= XK_GOTO
;
7987 ret
->canBreak
= TRUE
;
7991 exprNode
exprNode_continue (/*@only@*/ lltok l
, int qcontinue
)
7993 exprNode ret
= exprNode_createLoc (ctype_unknown
, fileloc_copy (lltok_getLoc (l
)));
7995 ret
->kind
= XPR_CONTINUE
;
7996 ret
->edata
= exprData_makeTok (l
);
7997 ret
->canBreak
= TRUE
;
7998 ret
->mustBreak
= TRUE
;
8000 if (qcontinue
== QSAFEBREAK
)
8004 else if (qcontinue
== QINNERCONTINUE
)
8006 if (!context_inDeepLoop ())
8009 (FLG_LOOPLOOPCONTINUE
,
8010 cstring_makeLiteral ("Continue statement marked with innercontinue "
8011 "is not inside a nested loop"),
8012 exprNode_loc (ret
));
8015 else if (qcontinue
== BADTOK
)
8017 if (context_inDeepLoop ())
8020 (FLG_LOOPLOOPCONTINUE
,
8021 cstring_makeLiteral ("Continue statement in nested loop"),
8022 exprNode_loc (ret
));
8027 llbuglit ("exprNode_continue: bad qcontinue");
8033 exprNode
exprNode_break (/*@only@*/ lltok l
, int bqual
)
8035 exprNode ret
= exprNode_createLoc (ctype_unknown
, fileloc_copy (lltok_getLoc (l
)));
8036 clause breakClause
= context_breakClause ();
8038 ret
->kind
= XPR_BREAK
;
8039 ret
->edata
= exprData_makeTok (l
);
8040 ret
->canBreak
= TRUE
;
8041 ret
->mustBreak
= TRUE
;
8043 if (breakClause
== NOCLAUSE
)
8047 cstring_makeLiteral ("Break not inside while, for or switch statement"),
8048 exprNode_loc (ret
));
8052 if (bqual
!= BADTOK
)
8059 if (breakClause
== SWITCHCLAUSE
)
8061 if (!context_inDeepSwitch ())
8063 voptgenerror (FLG_SYNTAX
,
8065 ("Break preceded by innerbreak is not in a deep switch"),
8066 exprNode_loc (ret
));
8071 if (!context_inDeepLoop ())
8073 voptgenerror (FLG_SYNTAX
,
8075 ("Break preceded by innerbreak is not in a deep loop"),
8076 exprNode_loc (ret
));
8081 if (breakClause
== SWITCHCLAUSE
)
8083 voptgenerror (FLG_SYNTAX
,
8085 ("Break preceded by loopbreak is breaking a switch"),
8086 exprNode_loc (ret
));
8090 if (breakClause
!= SWITCHCLAUSE
)
8094 message ("Break preceded by switchbreak is breaking %s",
8095 cstring_makeLiteralTemp
8096 ((breakClause
== WHILECLAUSE
8097 || breakClause
== DOWHILECLAUSE
) ? "a while loop"
8098 : (breakClause
== FORCLAUSE
) ? "a for loop"
8099 : (breakClause
== ITERCLAUSE
) ? "an iterator"
8101 exprNode_loc (ret
));
8109 if (breakClause
== SWITCHCLAUSE
)
8111 clause nextBreakClause
= context_nextBreakClause ();
8113 switch (nextBreakClause
)
8115 case NOCLAUSE
: break;
8121 (FLG_LOOPSWITCHBREAK
,
8122 cstring_makeLiteral ("Break statement in switch inside loop"),
8123 exprNode_loc (ret
));
8127 (FLG_SWITCHSWITCHBREAK
,
8128 cstring_makeLiteral ("Break statement in switch inside switch"),
8129 exprNode_loc (ret
));
8136 if (context_inDeepLoop ())
8140 cstring_makeLiteral ("Break statement in nested loop"),
8141 exprNode_loc (ret
));
8145 if (context_inDeepLoopSwitch ())
8148 (FLG_SWITCHLOOPBREAK
,
8149 cstring_makeLiteral ("Break statement in loop inside switch"),
8150 exprNode_loc (ret
));
8160 exprNode
exprNode_nullReturn (/*@only@*/ lltok t
)
8162 fileloc loc
= lltok_getLoc (t
);
8163 exprNode ret
= exprNode_createLoc (ctype_unknown
, fileloc_copy (loc
));
8165 context_returnFunction ();
8166 exprChecks_checkNullReturn (loc
);
8168 ret
->kind
= XPR_NULLRETURN
;
8169 ret
->edata
= exprData_makeTok (t
);
8170 ret
->exitCode
= XK_MUSTRETURN
;
8174 exprNode
exprNode_return (/*@only@*/ exprNode e
)
8178 if (exprNode_isError (e
))
8180 ret
= exprNode_createUnknown ();
8184 ret
= exprNode_createLoc (ctype_unknown
, fileloc_copy (e
->loc
));
8186 exprNode_checkUse (ret
, e
->sref
, e
->loc
);
8187 exprNode_checkReturn (e
);
8190 context_returnFunction ();
8191 ret
->kind
= XPR_RETURN
;
8192 ret
->edata
= exprData_makeSingle (e
);
8193 ret
->exitCode
= XK_MUSTRETURN
;
8198 exprNode
exprNode_comma (/*@only@*/ exprNode e1
, /*@only@*/ exprNode e2
)
8202 if (exprNode_isError (e1
))
8204 if (exprNode_isError (e2
))
8206 ret
= exprNode_createLoc (ctype_unknown
, fileloc_copy (g_currentloc
));
8210 ret
= exprNode_createPartialCopy (e2
);
8211 exprNode_checkUse (ret
, e2
->sref
, e2
->loc
);
8212 ret
->sref
= e2
->sref
;
8217 ret
= exprNode_createPartialCopy (e1
);
8219 exprNode_checkUse (ret
, e1
->sref
, e1
->loc
);
8221 if (!exprNode_isError (e2
))
8223 exprNode_mergeUSs (ret
, e2
);
8224 exprNode_checkUse (ret
, e2
->sref
, e2
->loc
);
8225 ret
->sref
= e2
->sref
;
8229 ret
->kind
= XPR_COMMA
;
8230 ret
->edata
= exprData_makePair (e1
, e2
);
8232 if (exprNode_isDefined (e1
))
8234 if (exprNode_isDefined (e2
))
8238 if (exprNode_mustEscape (e1
) || e1
->mustBreak
)
8242 message ("Second clause of comma expression is unreachable: %s",
8243 exprNode_unparse (e2
)),
8247 ret
->exitCode
= exitkind_combine (e1
->exitCode
, e2
->exitCode
);
8248 ret
->mustBreak
= e1
->mustBreak
|| e2
->mustBreak
;
8249 ret
->canBreak
= e1
->canBreak
|| e2
->canBreak
;
8253 if (exprNode_mustEscape (e1
) || e1
->mustBreak
)
8257 message ("Second clause of comma expression is unreachable: %s",
8258 exprNode_unparse (e2
)),
8262 ret
->exitCode
= e1
->exitCode
;
8263 ret
->canBreak
= e1
->canBreak
;
8268 if (exprNode_isDefined (e2
))
8270 ret
->exitCode
= e2
->exitCode
;
8271 ret
->mustBreak
= e2
->mustBreak
;
8272 ret
->canBreak
= e2
->canBreak
;
8279 static bool exprNode_checkOneInit (/*@notnull@*/ exprNode el
, exprNode val
)
8281 ctype t1
= exprNode_getType (el
);
8282 ctype t2
= exprNode_getType (val
);
8283 bool hasError
= FALSE
;
8285 DPRINTF (("Check one init: %s / %s",
8286 exprNode_unparse (el
),
8287 exprNode_unparse (val
)));
8289 if (ctype_isUnknown (t1
))
8291 voptgenerror (FLG_IMPTYPE
,
8292 message ("Variable has unknown (implicitly int) type: %s",
8293 exprNode_unparse (el
)),
8297 el
->typ
= ctype_int
;
8300 if (exprNode_isDefined (val
) && val
->kind
== XPR_INITBLOCK
)
8302 exprNodeList vals
= exprData_getArgs (val
->edata
);
8304 DPRINTF (("Check one init: %s", exprNodeList_unparse (vals
)));
8305 DPRINTF (("Type: %s", ctype_unparse (t1
)));
8307 if (ctype_isRealAP (t1
))
8312 if (ctype_isFixedArray (t1
))
8314 size_t nelements
= ctype_getArraySize (t1
);
8316 DPRINTF (("Checked array: %s / %d",
8317 ctype_unparse (t1
), nelements
));
8319 if (exprNode_isStringLiteral (val
))
8321 exprNode_checkStringLiteralLength (t1
, val
);
8325 if (exprNodeList_size (vals
) != size_toInt (nelements
))
8327 hasError
= optgenerror
8328 (exprNodeList_size (vals
) > size_toInt (nelements
)
8329 ? FLG_INITSIZE
: FLG_INITALLELEMENTS
,
8330 message ("Initializer block for "
8331 "%s has %d element%&, but declared as %s: %q",
8332 exprNode_unparse (el
),
8333 exprNodeList_size (vals
),
8335 exprNodeList_unparse (vals
)),
8341 exprNodeList_elements (vals
, oneval
)
8343 cstring istring
= message ("%d", i
);
8346 (exprNode_fakeCopy (el
),
8347 exprNode_numLiteral (ctype_int
, istring
,
8348 fileloc_copy (el
->loc
), i
));
8350 if (exprNode_isDefined (newel
))
8352 if (exprNodeList_size (vals
) == 1
8353 && ctype_isString (exprNode_getType (oneval
))
8354 && ctype_isChar (exprNode_getType (newel
)))
8356 exprNode_freeIniter (newel
);
8360 if (exprNode_checkOneInit (newel
, oneval
))
8365 if (nerrors
> 3 && exprNodeList_size (vals
) > 6)
8368 (message ("Additional initialization errors "
8369 "for %s not reported",
8370 exprNode_unparse (el
)),
8372 exprNode_freeIniter (newel
);
8377 exprNode_freeIniter (newel
);
8382 exprNode_freeIniter (newel
);
8387 cstring_free (istring
);
8390 } end_exprNodeList_elements
;
8393 else if (ctype_isStruct (ctype_realType (t1
)))
8395 uentryList fields
= ctype_getFields (t1
);
8398 if (uentryList_size (fields
) != exprNodeList_size (vals
))
8400 if (uentryList_size (fields
) > exprNodeList_size (vals
))
8402 hasError
= optgenerror
8404 message ("Initializer block for "
8405 "%s has %d field%&, but %s has %d field%&: %q",
8406 exprNode_unparse (el
),
8407 exprNodeList_size (vals
),
8409 uentryList_size (fields
),
8410 exprNodeList_unparse (vals
)),
8415 hasError
= optgenerror
8417 message ("Initializer block for "
8418 "%s has %d field%&, but %s has %d field%&: %q",
8419 exprNode_unparse (el
),
8420 exprNodeList_size (vals
),
8422 uentryList_size (fields
),
8423 exprNodeList_unparse (vals
)),
8429 exprNodeList_elements (vals
, oneval
)
8431 uentry thisfield
= uentryList_getN (fields
, i
);
8433 exprNode_fieldAccessAux (exprNode_fakeCopy (el
),
8435 uentry_getName (thisfield
));
8437 if (exprNode_isDefined (newel
))
8439 if (exprNode_checkOneInit (newel
, oneval
))
8444 exprNode_freeIniter (newel
);
8448 } end_exprNodeList_elements
;
8451 /* evans 2001-12-30: added to fix bug reported by Jim Zelenka */
8452 else if (ctype_isUnion (ctype_realType (t1
)))
8454 uentryList fields
= ctype_getFields (t1
);
8458 ** Union initializers set the first member always.
8461 DPRINTF (("Union initializer: %s / %s",
8462 exprNode_unparse (el
), ctype_unparse (ctype_realType (t1
))));
8464 if (exprNodeList_size (vals
) != 1)
8466 hasError
= optgenerror
8468 message ("Initializer block for union "
8469 "%s has %d elements, union initializers should have one element: %q",
8470 exprNode_unparse (el
),
8471 exprNodeList_size (vals
),
8472 exprNodeList_unparse (vals
)),
8477 exprNode oneval
= exprNodeList_head (vals
);
8478 uentry thisfield
= uentryList_getN (fields
, i
);
8480 exprNode_fieldAccessAux (exprNode_fakeCopy (el
),
8482 uentry_getName (thisfield
));
8484 if (exprNode_isDefined (newel
))
8486 if (exprNode_checkOneInit (newel
, oneval
))
8491 exprNode_freeIniter (newel
);
8497 hasError
= optgenerror
8499 message ("Initializer block used for "
8500 "%s where %t is expected: %s",
8501 exprNode_unparse (el
), t1
, exprNode_unparse (val
)),
8507 if (exprNode_isDefined (val
))
8509 doAssign (el
, val
, TRUE
);
8511 if (!exprNode_matchType (t1
, val
))
8513 hasError
= gentypeerror
8515 message ("Initial value of %s is type %t, "
8517 exprNode_unparse (el
),
8518 t2
, t1
, exprNode_unparse (val
)),
8527 static /*@notnull@*/ exprNode
8528 exprNode_makeInitializationAux (/*@temp@*/ idDecl t
)
8532 DPRINTF (("Initialization: %s", idDecl_unparse (t
)));
8534 if (usymtab_exists (idDecl_observeId (t
)))
8536 uentry ue
= usymtab_lookup (idDecl_observeId (t
));
8537 ret
= exprNode_createId (ue
);
8543 DPRINTF (("Unrecognized: %s", idDecl_unparse (t
)));
8545 ue
= uentry_makeUnrecognized (idDecl_observeId (t
), fileloc_copy (g_currentloc
));
8546 ret
= exprNode_fromIdentifierAux (ue
);
8549 ** No error - this happens in old style declarations:
8553 message ("Unrecognized identifier in intializer: %s", idDecl_observeId (t)),
8560 exprData_free (ret
->edata
, ret
->kind
);
8561 ret
->edata
= exprData_undefined
;
8562 ret
->exitCode
= XK_NEVERESCAPE
;
8563 ret
->mustBreak
= FALSE
;
8564 ret
->kind
= XPR_INIT
;
8568 exprNode
exprNode_makeEmptyInitialization (/*@only@*/ idDecl t
)
8570 exprNode ret
= exprNode_makeInitializationAux (t
);
8571 llassert (ret
->edata
== exprData_undefined
);
8572 ret
->edata
= exprData_makeInit (t
, exprNode_undefined
);
8576 exprNode
exprNode_makeInitialization (/*@only@*/ idDecl t
,
8577 /*@only@*/ exprNode e
)
8579 uentry ue
= usymtab_lookup (idDecl_observeId (t
));
8580 exprNode ret
= exprNode_makeInitializationAux (t
);
8581 fileloc loc
= exprNode_loc (e
);
8583 DPRINTF (("initialization: %s = %s", idDecl_unparse (t
), exprNode_unparse (e
)));
8585 if (exprNode_isError (e
))
8587 e
= exprNode_createUnknown ();
8588 /* error: assume initializer is defined */
8589 sRef_setDefined (ret
->sref
, g_currentloc
);
8590 ret
->edata
= exprData_makeInit (t
, e
);
8594 ctype ct
= ctype_realishType (ret
->typ
);
8599 ** was addSafeUse --- what's the problem?
8601 ** int x = 3, y = x ?
8604 exprData_free (ret
->edata
, ret
->kind
);
8605 ret
->edata
= exprData_makeInit (t
, e
);
8606 DPRINTF (("ret: %s", exprNode_unparse (ret
)));
8608 exprNode_checkUse (ret
, e
->sref
, e
->loc
);
8610 if (ctype_isUnknown (e
->typ
) && uentry_isValid (ue
))
8612 exprNode lhs
= exprNode_createId (ue
);
8615 ** static storage should be undefined before initializing
8618 if (uentry_isStatic (ue
))
8620 sRef_setDefState (lhs
->sref
, SS_PARTIAL
, fileloc_undefined
);
8623 (void) exprNode_checkOneInit (lhs
, e
);
8625 if (uentry_isStatic (ue
))
8627 sRef_setDefState (lhs
->sref
, SS_DEFINED
, fileloc_undefined
);
8630 exprNode_free (lhs
);
8634 if (!exprNode_matchType (ct
, e
))
8636 if (exprNode_isZero (e
) && ctype_isArrayPtr (ct
))
8643 (exprNode_getType (e
), e
, exprNode_getType (ret
), ret
,
8645 ("Variable %q initialized to type %t, expects %t: %s",
8646 uentry_getName (ue
), exprNode_getType (e
),
8647 exprNode_getType (ret
),
8648 exprNode_unparse (e
)),
8654 if (uentry_isStatic (ue
))
8656 sRef_setDefState (ret
->sref
, SS_PARTIAL
, fileloc_undefined
);
8659 if (exprNode_isStringLiteral (e
)
8660 && (ctype_isArray (ct
))
8661 && (ctype_isChar (ctype_realType (ctype_baseArrayPtr (ct
)))))
8664 ** If t is a char [], the literal is copied.
8667 exprNode_checkStringLiteralLength (ct
, e
);
8668 sRef_setDefState (ret
->sref
, SS_DEFINED
, e
->loc
);
8669 ret
->val
= multiVal_copy (e
->val
);
8671 sRef_setNullTerminatedState (ret
->sref
);
8673 if (multiVal_isDefined (e
->val
))
8675 cstring slit
= multiVal_forceString (e
->val
);
8676 sRef_setLen (ret
->sref
, size_toInt (cstring_length (slit
) + 1));
8679 if (ctype_isFixedArray (ct
))
8681 sRef_setSize (ret
->sref
, size_toInt (ctype_getArraySize (ct
)));
8686 doAssign (ret
, e
, TRUE
);
8689 if (uentry_isStatic (ue
))
8691 sRef_setDefState (ret
->sref
, SS_DEFINED
, fileloc_undefined
);
8695 if (context_inIterDef ())
8697 /* should check if it is yield */
8698 uentry_setUsed (ue
, loc
);
8705 exprNode_mergeUSs (ret
, e
);
8706 DPRINTF (("Ret: %s %p %p",
8707 exprNode_unparse (ret
),
8708 ret
->requiresConstraints
,
8709 ret
->ensuresConstraints
));
8711 DPRINTF (("Ret: %s %s %s",
8712 exprNode_unparse (ret
),
8713 constraintList_unparse (ret
->requiresConstraints
),
8714 constraintList_unparse (ret
->ensuresConstraints
)));
8718 exprNode
exprNode_iter (/*@observer@*/ uentry name
,
8719 /*@only@*/ exprNodeList alist
,
8720 /*@only@*/ exprNode body
,
8721 /*@observer@*/ uentry end
)
8726 llassert (uentry_isValid (name
));
8728 uentry_setUsed (name
, exprNode_loc (body
));
8730 ret
= exprNode_createPartialCopy (body
);
8731 iname
= uentry_getName (name
);
8733 if (uentry_isInvalid (end
))
8735 llerror (FLG_ITERBALANCE
,
8736 message ("Iter %s not balanced with end_%s", iname
, iname
));
8740 cstring ename
= uentry_getName (end
);
8742 if (!cstring_equalPrefixLit (ename
, "end_"))
8744 llerror (FLG_ITERBALANCE
, message ("Iter %s not balanced with end_%s: %s",
8745 iname
, iname
, ename
));
8749 if (!cstring_equal (iname
, cstring_suffix (ename
, 4)))
8751 llerror (FLG_ITERBALANCE
,
8752 message ("Iter %s not balanced with end_%s: %s",
8753 iname
, iname
, ename
));
8757 cstring_free (ename
);
8760 context_exitIterClause (body
);
8762 ret
->kind
= XPR_ITER
;
8763 ret
->edata
= exprData_makeIter (name
, alist
, body
, end
);
8765 if (uentry_isIter (name
))
8767 (void) checkArgsReal (name
, body
,
8768 uentry_getParams (name
), alist
, TRUE
, ret
);
8771 cstring_free (iname
);
8777 exprNode_iterNewId (/*@only@*/ cstring s
)
8779 exprNode e
= exprNode_new ();
8780 uentry ue
= uentryList_getN (uentry_getParams (getCurrentIter ()), iterParamNo ());
8782 llassert (processingIterVars ());
8784 e
->loc
= context_getSaveLocation ();
8786 if (fileloc_isUndefined (e
->loc
))
8788 fileloc_free (e
->loc
);
8789 e
->loc
= fileloc_copy (g_currentloc
);
8792 e
->uses
= sRefSet_new ();
8793 e
->sets
= sRefSet_new ();
8794 e
->msets
= sRefSet_new ();
8796 e
->val
= multiVal_unknown ();
8797 e
->guards
= guardSet_new ();
8798 e
->sref
= sRef_undefined
;
8799 e
->isJumpPoint
= FALSE
;
8800 e
->exitCode
= XK_NEVERESCAPE
;
8802 /*> missing fields, detected by splint <*/
8803 e
->canBreak
= FALSE
;
8804 e
->mustBreak
= FALSE
;
8805 e
->etext
= cstring_undefined
;
8807 if (uentry_isYield (ue
))
8809 uentry uue
= uentry_makeVariable (s
, uentry_getType (ue
),
8810 fileloc_copy (e
->loc
),
8814 uue
= usymtab_supEntrySrefReturn (uue
);
8816 sr
= uentry_getSref (uue
);
8817 sRef_mergeStateQuiet (sr
, uentry_getSref (ue
));
8818 sr
= uentry_getSref (uue
);
8819 sRef_setDefined (sr
, e
->loc
);
8821 e
->typ
= uentry_getType (uue
);
8823 e
->edata
= exprData_makeId (uue
);
8824 uentry_setUsed (uue
, g_currentloc
);
8830 sRef_setGlobalScope ();
8831 uue
= uentry_makeVariableLoc (s
, ctype_unknown
);
8833 e
->typ
= ctype_unknown
;
8834 e
->edata
= exprData_makeId (uue
);
8836 uentry_setUsed (uue
, e
->loc
);
8837 uentry_setHasNameError (uue
);
8839 if (context_getFlag (FLG_REPEATUNRECOG
))
8841 uentry_markOwned (uue
);
8845 usymtab_supGlobalEntry (uue
);
8848 sRef_clearGlobalScope ();
8850 voptgenerror (FLG_UNRECOG
, message ("Unrecognized identifier: %s", s
),
8857 exprNode_defineConstraints(e
);
8862 exprNode_iterExpr (/*@returned@*/ exprNode e
)
8864 if (!processingIterVars ())
8866 llcontbuglit ("checkIterParam: not in iter");
8870 if (uentry_isYield (uentryList_getN (uentry_getParams (getCurrentIter ()),
8873 if (exprNode_isDefined (e
))
8875 if (fileloc_isDefined (e
->loc
))
8879 message ("Yield parameter is not simple identifier: %s",
8880 exprNode_unparse (e
)),
8887 message ("Yield parameter is not simple identifier: %s",
8888 exprNode_unparse (e
)),
8898 exprNode_iterId (/*@observer@*/ uentry c
)
8902 llassert (processingIterVars ());
8904 ue
= uentryList_getN (uentry_getParams (getCurrentIter ()),
8907 if (uentry_isYield (ue
))
8909 ctype ct
= uentry_getType (ue
);
8910 exprNode e
= exprNode_createPlain (ct
);
8911 cstring name
= uentry_getName (c
);
8912 uentry le
= uentry_makeVariable (name
, ct
, fileloc_undefined
, FALSE
);
8914 uentry_setUsed (ue
, g_currentloc
);
8915 uentry_setHasNameError (ue
);
8917 cstring_free (name
);
8920 e
->edata
= exprData_makeId (le
);
8921 e
->loc
= context_getSaveLocation ();
8922 e
->sref
= uentry_getSref (le
);
8924 usymtab_supEntrySref (le
);
8926 if (!context_inHeader ())
8930 message ("Yield parameter shadows local declaration: %q",
8931 uentry_getName (c
)),
8932 fileloc_isDefined (e
->loc
) ? e
->loc
: g_currentloc
))
8934 uentry_showWhereDeclared (c
);
8941 return (exprNode_fromIdentifierAux (c
));
8944 exprNode
exprNode_iterStart (/*@observer@*/ uentry name
, /*@only@*/ exprNodeList alist
)
8946 exprNode ret
= exprNode_create (ctype_unknown
);
8948 ret
->kind
= XPR_ITERCALL
;
8949 ret
->edata
= exprData_makeIterCall (name
, alist
);
8951 if (uentry_isIter (name
))
8953 uentryList params
= uentry_getParams (name
);
8955 if (context_inIterDef ()
8956 && uentryList_size (params
) == exprNodeList_size (alist
))
8960 exprNodeList_elements (alist
, arg
)
8962 uentry parg
= uentryList_getN (params
, i
);
8964 if (uentry_isYield (parg
))
8966 uentry ue
= exprNode_getUentry (arg
);
8968 if (uentry_isValid (ue
))
8975 } end_exprNodeList_elements
;
8978 (void) checkArgsReal (name
, ret
, params
, alist
, TRUE
, ret
);
8979 checkUnspecCall (ret
, params
, alist
);
8985 /*@exposed@*/ sRef
exprNode_getSref (exprNode e
)
8987 if (exprNode_isDefined (e
))
8989 if (sRef_isInvalid (e
->sref
))
8992 e
->sref
= sRef_makeUnknown ();
8993 sRef_setAliasKind (e
->sref
, AK_ERROR
, fileloc_undefined
);
9004 return sRef_undefined
;
9008 /*@observer@*/ cstring
9009 exprNode_unparseFirst (exprNode e
)
9011 if (exprNode_isDefined (e
))
9015 if (e
->kind
== XPR_STMTLIST
9016 || e
->kind
== XPR_COMMA
|| e
->kind
== XPR_COND
)
9018 exprNode first
= exprData_getPairA (e
->edata
);
9020 if (exprNode_isDefined (first
))
9022 return (exprNode_unparseFirst (exprData_getPairA (e
->edata
)));
9026 return (cstring_makeLiteralTemp ("..."));
9030 ret
= cstring_elide (exprNode_unparse (e
), 20);
9031 cstring_markOwned (ret
);
9037 return cstring_makeLiteralTemp ("<error>");
9041 /*@observer@*/ cstring
9042 exprNode_unparse (/*@temp@*/ exprNode e
)
9044 if (exprNode_isError (e
))
9046 return cstring_makeLiteralTemp ("<error>");
9049 if (cstring_isDefined (e
->etext
))
9055 cstring ret
= exprNode_doUnparse (e
);
9057 /*@-modifies@*/ /* benevolent */
9064 /*@observer@*/ fileloc
9065 exprNode_loc (exprNode e
)
9067 if (exprNode_isError (e
))
9069 return (g_currentloc
);
9078 ** executes exprNode e
9079 ** recursively rexecutes as though in original parse using
9080 ** information in e->edata
9083 static /*@only@*/ exprNodeList
exprNodeList_effect (exprNodeList e
)
9085 exprNodeList ret
= exprNodeList_new ();
9087 exprNodeList_elements (e
, current
)
9089 exprNodeList_addh (ret
, exprNode_effect (current
));
9090 } end_exprNodeList_elements
;
9095 static /*@only@*/ exprNode
exprNode_effect (exprNode e
)
9096 /*@globals internalState@*/
9098 bool innerEffect
= inEffect
;
9104 context_clearJustPopped ();
9106 if (exprNode_isError (e
))
9108 ret
= exprNode_undefined
;
9113 ** Turn off expose and dependent transfer checking.
9114 ** Need to pass exposed internal nodes,
9115 ** [ copying would be a waste! ]
9116 ** [ Actually, I think I wasted a lot more time than its worth ]
9117 ** [ trying to do this. ]
9121 /*@-observertrans@*/
9122 /*@-dependenttrans@*/
9129 ret
= exprNode_addParens (exprData_getUopTok (data
),
9130 exprNode_effect (exprData_getUopNode (data
)));
9133 ret
= exprNode_assign (exprNode_effect (exprData_getOpA (data
)),
9134 exprNode_effect (exprData_getOpB (data
)),
9135 exprData_getOpTok (data
));
9138 ret
= exprNode_undefined
;
9141 ret
= exprNode_functionCall (exprNode_effect (exprData_getFcn (data
)),
9142 exprNodeList_effect (exprData_getArgs (data
)));
9155 cstring id
= exprData_getId (data
);
9156 uentry ue
= usymtab_lookupSafe (id
);
9158 ret
= exprNode_fromIdentifierAux (ue
);
9159 ret
->loc
= fileloc_update (ret
->loc
, e
->loc
);
9166 ret
= exprNode_arrayFetch (exprNode_effect (exprData_getPairA (data
)),
9167 exprNode_effect (exprData_getPairB (data
)));
9171 ** evans 2002-03-15: for && and ||, need to do the guards also
9172 ** this is what cgrammar.y does - should be
9173 ** able to avoid duplication, but need to
9174 ** time with grammar productions.
9177 DPRINTF (("Effect: %s", exprNode_unparse (e
)));
9179 if (lltok_getTok (exprData_getOpTok (data
)) == AND_OP
)
9181 exprNode e1
= exprNode_effect (exprData_getOpA (data
));
9183 exprNode_produceGuards (e1
);
9184 context_enterAndClause (e1
);
9185 e2
= exprNode_effect (exprData_getOpB (data
));
9187 ret
= exprNode_op (e1
, e2
,
9188 exprData_getOpTok (data
));
9190 context_exitAndClause (ret
, e2
);
9192 else if (lltok_getTok (exprData_getOpTok (data
)) == OR_OP
)
9194 exprNode e1
= exprNode_effect (exprData_getOpA (data
));
9196 exprNode_produceGuards (e1
);
9197 context_enterOrClause (e1
);
9198 e2
= exprNode_effect (exprData_getOpB (data
));
9200 ret
= exprNode_op (e1
, e2
,
9201 exprData_getOpTok (data
));
9203 context_exitOrClause (ret
, e2
);
9207 ret
= exprNode_op (exprNode_effect (exprData_getOpA (data
)),
9208 exprNode_effect (exprData_getOpB (data
)),
9209 exprData_getOpTok (data
));
9214 ret
= exprNode_postOp (exprNode_effect (exprData_getUopNode (data
)),
9215 exprData_getUopTok (data
));
9218 ret
= exprNode_preOp (exprNode_effect (exprData_getUopNode (data
)),
9219 exprData_getUopTok (data
));
9231 ret
= exprNode_vaArg (exprData_getCastTok (data
),
9232 exprNode_effect (exprData_getCastNode (data
)),
9233 exprData_getCastType (data
));
9237 ret
= exprNode_cast (exprData_getCastTok (data
),
9238 exprNode_effect (exprData_getCastNode (data
)),
9239 exprData_getCastType (data
));
9242 ret
= exprNode_iterStart (exprData_getIterCallIter (data
),
9244 (exprData_getIterCallArgs (data
)));
9248 ret
= exprNode_iter (exprData_getIterSname (data
),
9249 exprNodeList_effect (exprData_getIterAlist (data
)),
9250 exprNode_effect (exprData_getIterBody (data
)),
9251 exprData_getIterEname (data
));
9255 ret
= exprNode_for (exprNode_effect (exprData_getPairA (data
)),
9256 exprNode_effect (exprData_getPairB (data
)));
9260 ret
= exprNode_forPred (exprNode_effect (exprData_getTripleInit (data
)),
9261 exprNode_effect (exprData_getTripleTest (data
)),
9262 exprNode_effect (exprData_getTripleInc (data
)));
9266 ret
= exprNode_createTok (exprData_getTok (data
));
9270 ret
= exprNode_goto (exprData_getLiteral (data
));
9271 ret
->loc
= fileloc_update (ret
->loc
, e
->loc
);
9275 ret
= exprNode_continue (exprData_getTok (data
), QSAFEBREAK
);
9279 ret
= exprNode_break (exprData_getTok (data
), QSAFEBREAK
);
9283 ret
= exprNode_return (exprNode_effect (exprData_getSingle (data
)));
9286 case XPR_NULLRETURN
:
9287 ret
= exprNode_nullReturn (exprData_getTok (data
));
9291 ret
= exprNode_comma (exprNode_effect (exprData_getPairA (data
)),
9292 exprNode_effect (exprData_getPairB (data
)));
9296 ret
= exprNode_cond (exprNode_effect (exprData_getTriplePred (data
)),
9297 exprNode_effect (exprData_getTripleTrue (data
)),
9298 exprNode_effect (exprData_getTripleFalse (data
)));
9301 ret
= exprNode_if (exprNode_effect (exprData_getPairA (data
)),
9302 exprNode_effect (exprData_getPairB (data
)));
9306 ret
= exprNode_ifelse (exprNode_effect (exprData_getTriplePred (data
)),
9307 exprNode_effect (exprData_getTripleTrue (data
)),
9308 exprNode_effect (exprData_getTripleFalse (data
)));
9311 ret
= exprNode_whilePred (exprData_getSingle (data
));
9315 ret
= exprNode_while (exprNode_effect (exprData_getPairA (data
)),
9316 exprNode_effect (exprData_getPairB (data
)));
9320 ret
= exprNode_doWhile (exprNode_effect (exprData_getPairA (data
)),
9321 exprNode_effect (exprData_getPairB (data
)));
9325 ret
= exprNode_makeBlock (exprNode_effect (exprData_getSingle (data
)));
9329 ret
= exprNode_statement (exprNode_effect (exprData_getUopNode (data
)),
9330 exprData_getUopTok (data
));
9334 ret
= exprNode_concat (exprNode_effect (exprData_getPairA (data
)),
9335 exprNode_effect (exprData_getPairB (data
)));
9340 ret
= exprNode_caseMarker
9341 (exprNode_effect (exprData_getSingle (data
)),
9347 ret
= exprNode_createTok (exprData_getTok (data
));
9351 ret
= exprNode_switch (exprNode_effect (exprData_getPairA (data
)),
9352 exprNode_effect (exprData_getPairB (data
)));
9356 ret
= exprNode_makeInitialization
9357 (exprData_getInitId (data
),
9358 exprNode_effect (exprData_getInitNode (data
)));
9362 ret
= exprNode_fieldAccessAux
9363 (exprNode_effect (exprData_getFieldNode (data
)),
9364 exprNode_loc (exprData_getFieldNode (data
)),
9365 cstring_copy (exprData_getFieldName (data
)));
9369 ret
= exprNode_arrowAccessAux
9370 (exprNode_effect (exprData_getFieldNode (data
)),
9371 exprNode_loc (exprData_getFieldNode (data
)),
9372 cstring_copy (exprData_getFieldName (data
)));
9375 case XPR_STRINGLITERAL
:
9389 /*@=observertrans@*/
9391 /*@=dependenttrans@*/
9402 static /*@observer@*/ cstring
exprNode_rootVarName (exprNode e
)
9407 if (exprNode_isError (e
))
9409 return cstring_undefined
;
9417 ret
= exprNode_rootVarName (exprData_getUopNode (data
));
9420 ret
= exprNode_rootVarName (exprData_getOpA (data
));
9424 ret
= exprData_getId (data
);
9427 ret
= idDecl_getName (exprData_getInitId (data
));
9430 ret
= cstring_undefined
;
9437 static /*@only@*/ cstring
exprNode_doUnparse (exprNode e
)
9442 if (exprNode_isError (e
))
9444 static /*@only@*/ cstring error
= cstring_undefined
;
9446 if (!cstring_isDefined (error
))
9448 error
= cstring_makeLiteral ("<error>");
9459 ret
= message ("(%s)", exprNode_unparse (exprData_getUopNode (e
->edata
)));
9462 ret
= message ("%s %s %s",
9463 exprNode_unparse (exprData_getOpA (data
)),
9464 lltok_unparse (exprData_getOpTok (data
)),
9465 exprNode_unparse (exprData_getOpB (data
)));
9468 ret
= message ("%s(%q)",
9469 exprNode_unparse (exprData_getFcn (data
)),
9470 exprNodeList_unparse (exprData_getArgs (data
)));
9473 ret
= message ("{ %q }", exprNodeList_unparse (exprData_getArgs (data
)));
9476 ret
= cstring_undefined
;
9479 ret
= message ("%s:", exprData_getId (data
));
9483 ret
= cstring_copy (exprData_getId (data
));
9486 ret
= message ("%s[%s]", exprNode_unparse (exprData_getPairA (data
)),
9487 exprNode_unparse (exprData_getPairB (data
)));
9490 ret
= message ("<body>");
9493 ret
= message ("%s %s %s",
9494 exprNode_unparse (exprData_getOpA (data
)),
9495 lltok_unparse (exprData_getOpTok (data
)),
9496 exprNode_unparse (exprData_getOpB (data
)));
9500 ret
= message ("%s%s",
9501 lltok_unparse (exprData_getUopTok (data
)),
9502 exprNode_unparse (exprData_getUopNode (data
)));
9506 ret
= message ("%s%s",
9507 exprNode_unparse (exprData_getUopNode (data
)),
9508 lltok_unparse (exprData_getUopTok (data
)));
9512 ret
= message ("offsetof(%s,%q)",
9513 ctype_unparse (qtype_getType (exprData_getOffsetType (data
))),
9514 cstringList_unparseSep (exprData_getOffsetName (data
), cstring_makeLiteralTemp (".")));
9518 ret
= message ("sizeof(%s)", ctype_unparse (qtype_getType (exprData_getType (data
))));
9522 ret
= message ("sizeof(%s)", exprNode_unparse (exprData_getSingle (data
)));
9526 ret
= message ("alignof(%s)", ctype_unparse (qtype_getType (exprData_getType (data
))));
9530 ret
= message ("alignof(%s)", exprNode_unparse (exprData_getSingle (data
)));
9534 ret
= message ("va_arg(%s, %q)",
9535 exprNode_unparse (exprData_getCastNode (data
)),
9536 qtype_unparse (exprData_getCastType (data
)));
9540 ret
= message ("%q(%q)",
9541 uentry_getName (exprData_getIterCallIter (data
)),
9542 exprNodeList_unparse (exprData_getIterCallArgs (data
)));
9545 ret
= message ("%q(%q) %s %q",
9546 uentry_getName (exprData_getIterSname (data
)),
9547 exprNodeList_unparse (exprData_getIterAlist (data
)),
9548 exprNode_unparse (exprData_getIterBody (data
)),
9549 uentry_getName (exprData_getIterEname (data
)));
9552 ret
= message ("(%q)%s",
9553 qtype_unparse (exprData_getCastType (data
)),
9554 exprNode_unparse (exprData_getCastNode (data
)));
9558 ret
= message ("%s %s",
9559 exprNode_unparse (exprData_getPairA (data
)),
9560 exprNode_unparse (exprData_getPairB (data
)));
9564 ret
= message ("for (%s; %s; %s)",
9565 exprNode_unparse (exprData_getTripleInit (data
)),
9566 exprNode_unparse (exprData_getTripleTest (data
)),
9567 exprNode_unparse (exprData_getTripleInc (data
)));
9571 ret
= message ("goto %s", exprData_getLiteral (data
));
9575 ret
= cstring_makeLiteral ("continue");
9579 ret
= cstring_makeLiteral ("break");
9583 ret
= message ("return %s", exprNode_unparse (exprData_getSingle (data
)));
9586 case XPR_NULLRETURN
:
9587 ret
= cstring_makeLiteral ("return");
9591 ret
= message ("%s, %s",
9592 exprNode_unparse (exprData_getPairA (data
)),
9593 exprNode_unparse (exprData_getPairB (data
)));
9597 ret
= message ("%s ? %s : %s",
9598 exprNode_unparse (exprData_getTriplePred (data
)),
9599 exprNode_unparse (exprData_getTripleTrue (data
)),
9600 exprNode_unparse (exprData_getTripleFalse (data
)));
9603 ret
= message ("if (%s) %s",
9604 exprNode_unparse (exprData_getPairA (data
)),
9605 exprNode_unparse (exprData_getPairB (data
)));
9609 ret
= message ("if (%s) %s else %s",
9610 exprNode_unparse (exprData_getTriplePred (data
)),
9611 exprNode_unparse (exprData_getTripleTrue (data
)),
9612 exprNode_unparse (exprData_getTripleFalse (data
)));
9615 ret
= message ("while (%s) %s",
9616 exprNode_unparse (exprData_getPairA (data
)),
9617 exprNode_unparse (exprData_getPairB (data
)));
9621 ret
= cstring_copy (exprNode_unparse (exprData_getSingle (data
)));
9625 ret
= cstring_copy (lltok_unparse (exprData_getTok (data
)));
9629 ret
= message ("do { %s } while (%s)",
9630 exprNode_unparse (exprData_getPairB (data
)),
9631 exprNode_unparse (exprData_getPairA (data
)));
9635 ret
= message ("{ %s }", exprNode_unparse (exprData_getSingle (data
)));
9636 /* evans 2002-02-20 was unparseFirst! */
9640 ret
= message ("%s;", exprNode_unparse (exprData_getUopNode (data
)));
9644 if (exprNode_isStatement (exprData_getPairA (data
)))
9647 ** statement expressions already print the ;
9650 ret
= message ("%s %s",
9651 exprNode_unparse (exprData_getPairA (data
)),
9652 exprNode_unparse (exprData_getPairB (data
)));
9656 ret
= message ("%s; %s",
9657 exprNode_unparse (exprData_getPairA (data
)),
9658 exprNode_unparse (exprData_getPairB (data
)));
9664 ret
= cstring_makeLiteral ("default:");
9668 ret
= message ("switch (%s) %s",
9669 exprNode_unparse (exprData_getPairA (data
)),
9670 exprNode_unparse (exprData_getPairB (data
)));
9675 ret
= message ("case %s:",
9676 exprNode_unparse (exprData_getSingle (data
)));
9680 if (exprNode_isError (exprData_getInitNode (data
)))
9682 ret
= message ("%q", idDecl_unparseC (exprData_getInitId (data
)));
9686 ret
= message ("%q = %s",
9687 idDecl_unparseC (exprData_getInitId (data
)),
9688 exprNode_unparse (exprData_getInitNode (data
)));
9693 ret
= message ("%s.%s",
9694 exprNode_unparse (exprData_getFieldNode (data
)),
9695 exprData_getFieldName (data
));
9699 ret
= message ("%s->%s",
9700 exprNode_unparse (exprData_getFieldNode (data
)),
9701 exprData_getFieldName (data
));
9704 case XPR_STRINGLITERAL
:
9705 if (ctype_isWideString (e
->typ
))
9707 ret
= message ("L\"%s\"", exprData_getLiteral (data
));
9711 ret
= message ("\"%s\"", exprData_getLiteral (data
));
9716 ret
= cstring_copy (exprData_getLiteral (data
));
9720 ret
= cstring_makeLiteral ("<node>");
9728 exprNode_isInitializer (exprNode e
)
9730 return (exprNode_isDefined (e
)
9731 && e
->kind
== XPR_INIT
);
9735 exprNode_isCharLiteral (exprNode e
)
9737 if (exprNode_isDefined (e
))
9739 return (multiVal_isChar (exprNode_getValue (e
)));
9748 exprNode_isNumLiteral (exprNode e
)
9750 if (exprNode_isDefined (e
))
9752 return (multiVal_isInt (exprNode_getValue (e
)));
9761 exprNode_isFalseConstant (exprNode e
)
9763 if (exprNode_isDefined (e
))
9765 cstring s
= exprNode_rootVarName (e
);
9767 if (cstring_equal (s
, context_getFalseName ()))
9777 exprNode_matchLiteral (ctype expected
, exprNode e
)
9779 if (exprNode_isDefined (e
))
9781 multiVal m
= exprNode_getValue (e
);
9783 if (multiVal_isDefined (m
))
9785 if (multiVal_isInt (m
))
9787 long int val
= multiVal_forceInt (m
);
9789 if (ctype_isNumAbstract (expected
)
9790 && context_flagOn (FLG_NUMABSTRACTLIT
, exprNode_loc (e
)))
9795 if (ctype_isDirectBool (ctype_realishType (expected
)))
9799 return FALSE
; /* really?! return TRUE; allow use of 0 for FALSE */
9807 if (ctype_isRealInt (expected
))
9810 ** unsigned <- [ constant >= 0 is okay ]
9813 if (ctype_isUnsigned (expected
))
9822 ** No checks on sizes of integers...maybe add
9826 DPRINTF (("Here: %s => %s", exprNode_unparse (e
), ctype_unparse (expected
)));
9827 DPRINTF (("Type: %s / %s", ctype_unparse (exprNode_getType (e
)),
9828 bool_unparse (ctype_isInt (exprNode_getType (e
)))));
9830 if (context_getFlag (FLG_NUMLITERAL
)
9831 && (ctype_isRegularInt (exprNode_getType (e
)) || val
== 0)) {
9837 return FALSE
; /* evs 2000-05-17: previously, always returned TRUE */
9841 else if (ctype_isChar (expected
))
9845 else if (ctype_isArrayPtr (expected
))
9848 ** evans 2001-10-14: We allow 0 to match any pointer, but only if the type matches or is void *.
9853 if (ctype_match (exprNode_getType (e
), expected
)
9854 || ctype_isVoidPointer (exprNode_getType (e
)))
9864 else if (ctype_isAnyFloat (expected
))
9866 return (context_getFlag (FLG_NUMLITERAL
));
9873 else if (multiVal_isDouble (m
))
9875 if (ctype_isAnyFloat (expected
))
9880 else if (multiVal_isChar (m
))
9882 /*signed? */ char val
= multiVal_forceChar (m
);
9884 if (ctype_isChar (expected
))
9886 if (ctype_isUnsigned (expected
) && ((int) val
) < 0)
9907 exprNode_matchType (ctype expected
, exprNode e
)
9911 if (!exprNode_isDefined (e
)) return TRUE
;
9913 actual
= ctype_realishType (exprNode_getType (e
));
9915 if (ctype_match (ctype_realishType (expected
), actual
))
9920 llassert (!exprNode_isError (e
));
9921 return (exprNode_matchLiteral (expected
, e
));
9925 exprNode_matchTypes (exprNode e1
, exprNode e2
)
9930 if (!exprNode_isDefined (e1
)) return TRUE
;
9931 if (!exprNode_isDefined (e2
)) return TRUE
;
9934 ** realish type --- keep bools, bools
9937 t1
= ctype_realishType (exprNode_getType (e1
));
9938 t2
= ctype_realishType (exprNode_getType (e2
));
9940 if (ctype_match (t1
, t2
))
9945 DPRINTF (("Matching literal! %s %s %s %s",
9946 ctype_unparse (t1
), exprNode_unparse (e2
),
9947 ctype_unparse (t2
), exprNode_unparse (e1
)));
9949 return (exprNode_matchLiteral (t1
, e2
) || exprNode_matchLiteral (t2
, e1
));
9957 exprNode_matchArgType (ctype ct
, exprNode e
)
9961 if (!exprNode_isDefined (e
))
9966 et
= ctype_realType (exprNode_getType (e
));
9968 if (ctype_matchArg (ct
, et
)) return TRUE
;
9970 llassert (!exprNode_isError (e
));
9971 return (exprNode_matchLiteral (ct
, e
));
9974 static /*@only@*/ exprNodeSList
9975 exprNode_flatten (/*@dependent@*/ exprNode e
) /*@*/
9977 if (exprNode_isDefined (e
))
9979 if (e
->kind
== XPR_STMTLIST
)
9981 return (exprNodeSList_append
9982 (exprNode_flatten (exprData_getPairA (e
->edata
)),
9983 exprNode_flatten (exprData_getPairB (e
->edata
))));
9985 else if (e
->kind
== XPR_BLOCK
)
9987 return (exprNode_flatten (exprData_getSingle (e
->edata
)));
9991 return (exprNodeSList_singleton (e
));
9995 return exprNodeSList_new ();
9998 static /*@exposed@*/ exprNode
9999 exprNode_lastStatement (/*@returned@*/ exprNode e
)
10001 if (exprNode_isDefined (e
))
10003 if (e
->kind
== XPR_STMTLIST
)
10005 exprNode b
= exprData_getPairB (e
->edata
);
10007 if (exprNode_isDefined (b
))
10009 return exprNode_lastStatement (b
);
10013 return exprNode_lastStatement (exprData_getPairA (e
->edata
));
10016 else if (e
->kind
== XPR_BLOCK
)
10018 return (exprNode_lastStatement (exprData_getSingle (e
->edata
)));
10026 return exprNode_undefined
;
10029 static /*@exposed@*/ exprNode
10030 exprNode_firstStatement (/*@returned@*/ exprNode e
)
10032 if (exprNode_isDefined (e
))
10034 if (e
->kind
== XPR_STMTLIST
)
10036 exprNode b
= exprData_getPairA (e
->edata
);
10038 if (exprNode_isDefined (b
))
10040 return exprNode_firstStatement (b
);
10044 return exprNode_firstStatement (exprData_getPairB (e
->edata
));
10047 else if (e
->kind
== XPR_BLOCK
)
10049 return (exprNode_firstStatement (exprData_getSingle (e
->edata
)));
10057 return exprNode_undefined
;
10061 exprNode_mergeUSs (exprNode res
, exprNode other
)
10063 if (exprNode_isDefined (res
) && exprNode_isDefined (other
))
10065 res
->msets
= sRefSet_union (res
->msets
, other
->msets
);
10066 res
->sets
= sRefSet_union (res
->sets
, other
->sets
);
10067 res
->uses
= sRefSet_union (res
->uses
, other
->uses
);
10072 exprNode_mergeCondUSs (exprNode res
, exprNode other1
, exprNode other2
)
10074 if (exprNode_isDefined (res
))
10076 if (exprNode_isDefined (other1
))
10078 res
->sets
= sRefSet_union (res
->sets
, other1
->sets
);
10079 res
->msets
= sRefSet_union (res
->msets
, other1
->msets
);
10080 res
->uses
= sRefSet_union (res
->uses
, other1
->uses
);
10082 if (exprNode_isDefined (other2
))
10084 res
->sets
= sRefSet_union (res
->sets
, other2
->sets
);
10085 res
->msets
= sRefSet_union (res
->msets
, other2
->msets
);
10086 res
->uses
= sRefSet_union (res
->uses
, other2
->uses
);
10092 ** modifies e->uses
10094 ** Reports errors is s is not defined.
10098 exprNode_addUse (exprNode e
, /*@exposed@*/ sRef s
)
10100 if (exprNode_isDefined (e
))
10102 e
->uses
= sRefSet_insert (e
->uses
, s
);
10107 exprNode_checkUse (exprNode e
, /*@exposed@*/ sRef s
, fileloc loc
)
10109 if (sRef_isKnown (s
) && !sRef_isConst (s
))
10112 ** need to check all outer types are useable
10115 DPRINTF (("Check use: %s / %s",
10116 exprNode_unparse (e
), sRef_unparse (s
)));
10118 exprNode_addUse (e
, s
);
10120 if (!context_inProtectVars ())
10123 ** only report the deepest error
10126 sRef errorRef
= sRef_undefined
;
10127 sRef lastRef
= sRef_undefined
;
10128 bool deadRef
= FALSE
;
10129 bool unuseable
= FALSE
;
10130 bool errorMaybe
= FALSE
;
10132 while (sRef_isValid (s
) && sRef_isKnown (s
))
10134 ynm readable
= sRef_isValidLvalue (s
);
10136 DPRINTF (("Readable: %s / %s",
10137 sRef_unparseFull (s
), ynm_unparse (readable
)));
10139 if (!(ynm_toBoolStrict (readable
)))
10141 if (ynm_isMaybe (readable
))
10143 lastRef
= errorRef
;
10145 DPRINTF (("Setting ERROR: %s", sRef_unparseFull (s
)));
10146 deadRef
= sRef_isPossiblyDead (errorRef
);
10147 unuseable
= sRef_isUnuseable (errorRef
);
10152 lastRef
= errorRef
;
10154 DPRINTF (("Setting ERROR: %s", sRef_unparseFull (s
)));
10155 deadRef
= sRef_isDead (errorRef
);
10156 unuseable
= sRef_isUnuseable (errorRef
);
10157 errorMaybe
= FALSE
;
10161 if (!sRef_isPartial (s))
10163 DPRINTF (("Defining! %s", sRef_unparseFull (s)));
10164 sRef_setDefined (s, loc);
10165 DPRINTF (("Defining! %s", sRef_unparseFull (s)));
10170 s
= sRef_getBaseSafe (s
);
10173 if (sRef_isValid (errorRef
))
10175 if (sRef_isValid (lastRef
) && sRef_isField (lastRef
)
10176 && sRef_isPointer (errorRef
))
10178 errorRef
= lastRef
;
10179 DPRINTF (("errorRef: %s", sRef_unparseFull (errorRef
)));
10184 if (sRef_isThroughArrayFetch (errorRef
))
10187 (FLG_STRICTUSERELEASED
,
10188 message ("%q %q may be used after being released",
10189 sRef_unparseKindNamePlain (errorRef
),
10190 sRef_unparse (errorRef
)),
10193 sRef_showRefKilled (errorRef
);
10195 if (sRef_isKept (errorRef
))
10197 sRef_clearAliasState (errorRef
, loc
);
10203 DPRINTF (("HERE: %s", sRef_unparseFull (errorRef
)));
10207 message ("%q %q %qused after being released",
10208 sRef_unparseKindNamePlain (errorRef
),
10209 sRef_unparse (errorRef
),
10210 cstring_makeLiteral (errorMaybe
10211 ? "may be " : "")),
10214 sRef_showRefKilled (errorRef
);
10216 if (sRef_isKept (errorRef
))
10218 sRef_clearAliasState (errorRef
, loc
);
10223 else if (unuseable
)
10227 message ("%q %q%qused in inconsistent state",
10228 sRef_unparseKindName (errorRef
),
10229 sRef_unparseOpt (errorRef
),
10230 cstring_makeLiteral (errorMaybe
? "may be " : "")),
10233 sRef_showStateInconsistent (errorRef
);
10238 DPRINTF (("HERE: %s", sRef_unparseFull (errorRef
)));
10242 message ("%q %q%qused before definition",
10243 sRef_unparseKindName (errorRef
),
10244 sRef_unparseOpt (errorRef
),
10245 cstring_makeLiteral (errorMaybe
? "may be " : "")),
10251 DPRINTF (("Error: %s", sRef_unparseFull (errorRef
)));
10254 sRef_setDefined (errorRef
, loc
);
10256 if (sRef_isAddress (errorRef
))
10258 sRef_setDefined (sRef_getRootBase (errorRef
), loc
);
10260 } /* end is error */
10268 checkSafeUse (exprNode e
, /*@exposed@*/ sRef s
)
10270 if (exprNode_isDefined (e
) && sRef_isKnown (s
))
10272 e
->uses
= sRefSet_insert (e
->uses
, s
);
10277 exprNode_checkSetAny (exprNode e
, /*@dependent@*/ cstring name
)
10279 if (exprNode_isDefined (e
))
10281 e
->sets
= sRefSet_insert (e
->sets
, sRef_makeUnconstrained (name
));
10286 exprNode_checkSet (exprNode e
, /*@exposed@*/ sRef s
)
10288 sRef defines
= sRef_undefined
;
10290 if (sRef_isValid (s
) && !sRef_isNothing (s
))
10292 uentry ue
= sRef_getBaseUentry (s
);
10294 if (uentry_isValid (ue
))
10296 uentry_setLset (ue
);
10299 if (!ynm_toBoolStrict (sRef_isWriteable (s
)))
10301 voptgenerror (FLG_USEDEF
,
10302 message ("Attempt to set unuseable storage: %q",
10307 if (sRef_isMeaningful (s
))
10309 if (sRef_isDead (s
))
10311 sRef base
= sRef_getBaseSafe (s
);
10313 if (sRef_isValid (base
)
10314 && sRef_isDead (base
))
10316 sRef_setPartial (s
, exprNode_loc (e
));
10319 defines
= s
; /* okay - modifies for only param */
10321 else if (sRef_isPartial (s
))
10323 sRef eref
= exprNode_getSref (e
);
10325 if (!sRef_isPartial (eref
))
10328 ** should do something different here???
10331 sRef_setDefinedComplete (eref
, exprNode_loc (e
));
10335 sRef_setPartialDefinedComplete (eref
, exprNode_loc (e
));
10338 if (sRef_isMeaningful (eref
))
10347 else if (sRef_isAllocated (s
))
10349 sRef eref
= exprNode_getSref (e
);
10352 if (!sRef_isAllocated (eref
))
10354 sRef_setDefinedComplete (eref
, exprNode_loc (e
));
10358 sRef base
= sRef_getBaseSafe (eref
);
10360 if (sRef_isValid (base
))
10362 sRef_setPdefined (base
, exprNode_loc (e
));
10370 sRef_setDefinedNCComplete (s
, exprNode_loc (e
));
10375 else /* not meaningful...but still need to insert it */
10381 if (exprNode_isDefined (e
) && sRef_isValid (defines
))
10383 e
->sets
= sRefSet_insert (e
->sets
, defines
);
10388 exprNode_checkMSet (exprNode e
, /*@exposed@*/ sRef s
)
10390 if (sRef_isValid (s
) && !sRef_isNothing (s
))
10392 uentry ue
= sRef_getBaseUentry (s
);
10394 if (uentry_isValid (ue
))
10396 uentry_setLset (ue
);
10399 if (!ynm_toBoolStrict (sRef_isWriteable (s
)))
10401 voptgenerror (FLG_USEDEF
,
10402 message ("Attempt to set unuseable storage: %q", sRef_unparse (s
)),
10406 if (sRef_isMeaningful (s
))
10408 sRef_setDefinedComplete (s
, exprNode_loc (e
));
10411 if (exprNode_isDefined (e
))
10413 e
->msets
= sRefSet_insert (e
->msets
, s
);
10419 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode fcn
, uentryList params
, exprNodeList args
)
10421 checkAnyCall (fcn
, cstring_undefined
, params
, args
,
10422 FALSE
, sRefSet_undefined
, FALSE
, 0);
10426 checkOneArg (uentry ucurrent
, /*@notnull@*/ exprNode current
,
10427 /*@dependent@*/ exprNode fcn
, bool isSpec
, int argno
, int totargs
)
10431 if (uentry_isYield (ucurrent
))
10433 sRef_setDefined (exprNode_getSref (current
), exprNode_loc (current
));
10434 exprNode_checkSet (current
, current
->sref
);
10438 if (uentry_isSefParam (ucurrent
))
10440 sRefSet sets
= current
->sets
;
10441 sRef ref
= exprNode_getSref (current
);
10443 if (sRef_isMacroParamRef (ref
))
10445 uentry ue
= sRef_getUentry (ref
);
10447 if (!uentry_isSefParam (ue
))
10452 ("Parameter %d to %s is declared sef, but "
10453 "the argument is a macro parameter declared "
10455 argno
, exprNode_unparse (fcn
),
10456 exprNode_unparse (current
)),
10457 exprNode_loc (current
));
10461 if (!sRefSet_isEmpty (sets
))
10463 sRefSet reported
= sRefSet_undefined
;
10465 sRefSet_realElements (current
->sets
, el
)
10467 if (sRefSet_isSameNameMember (reported
, el
))
10469 ; /* don't report again */
10473 if (sRef_isUnconstrained (el
))
10478 ("Parameter %d to %s is declared sef, but "
10479 "the argument calls unconstrained function %s "
10480 "(no guarantee it will not modify something): %s",
10481 argno
, exprNode_unparse (fcn
),
10482 sRef_unconstrainedName (el
),
10483 exprNode_unparse (current
)),
10484 exprNode_loc (current
));
10491 ("Parameter %d to %s is declared sef, but "
10492 "the argument may modify %q: %s",
10493 argno
, exprNode_unparse (fcn
),
10495 exprNode_unparse (current
)),
10496 exprNode_loc (current
));
10499 } end_sRefSet_realElements
;
10503 transferChecks_passParam (current
, ucurrent
, isSpec
, fcn
, argno
, totargs
);
10504 exprNode_mergeUSs (fcn
, current
);
10509 checkAnyCall (/*@dependent@*/ exprNode fcn
,
10510 /*@dependent@*/ cstring fname
,
10513 bool hasMods
, sRefSet mods
,
10518 int nargs
= exprNodeList_size (args
);
10523 ** concat all args ud's to f, add each arg sref as a use unless
10524 ** it was specified as "out", in which case it is a def.
10527 uentryList_reset (pn
);
10530 ** aliasing checks:
10532 ** if paramn is only or unique, no other arg may alias argn
10535 exprNodeList_elements (args
, current
)
10539 if (exprNode_isDefined (current
))
10541 if ((!uentryList_isUndefined (pn
) && !uentryList_isFinished (pn
)))
10543 uentry ucurrent
= uentryList_current (pn
);
10545 if (specialArgs
== 0
10546 || (paramno
< specialArgs
))
10548 checkOneArg (ucurrent
, current
, fcn
, isSpec
, paramno
, nargs
);
10550 if (context_maybeSet (FLG_ALIASUNIQUE
))
10552 if (uentry_isOnly (ucurrent
)
10553 || uentry_isUnique (ucurrent
))
10555 checkUniqueParams (fcn
, current
, args
,
10556 paramno
, ucurrent
);
10561 else /* uentry is undefined */
10563 if (specialArgs
== 0)
10565 exprNode_checkUseParam (current
);
10568 exprNode_mergeUSs (fcn
, current
);
10571 uentryList_advanceSafe (pn
);
10572 } end_exprNodeList_elements
;
10578 sRefSet_allElements (mods
, s
)
10581 sRef rb
= sRef_getRootBase (s
);
10583 if (sRef_isFileOrGlobalScope (rb
))
10585 context_usedGlobal (rb
);
10588 fb
= sRef_fixBaseParam (s
, args
);
10590 if (!sRef_isMacroParamRef (fb
))
10592 if (sRef_isNothing (fb
))
10598 if (sRef_isValid (fb
))
10600 uentry ue
= sRef_getBaseUentry (s
);
10602 if (uentry_isValid (ue
))
10604 uentry_setLset (ue
);
10608 fcn
->sets
= sRefSet_insert (fcn
->sets
, fb
);
10611 sRef_clearDerivedComplete (s
);
10612 } end_sRefSet_allElements
;
10618 if (context_hasMods ())
10620 if (context_maybeSet (FLG_MODUNCON
))
10624 message ("Undetected modification possible "
10625 "from call to unconstrained function %s: %s",
10627 exprNode_unparse (fcn
)),
10628 exprNode_loc (fcn
));
10633 if (context_maybeSet (FLG_MODUNCONNOMODS
)
10634 && !(context_inIterDef () || context_inIterEnd ()))
10637 (FLG_MODUNCONNOMODS
,
10638 message ("Undetected modification possible "
10639 "from call to unconstrained function %s: %s",
10641 exprNode_unparse (fcn
)),
10642 exprNode_loc (fcn
));
10646 exprNode_checkSetAny (fcn
, fname
);
10650 void exprNode_checkUseParam (exprNode current
)
10652 if (exprNode_isDefined (current
))
10654 exprNode_checkUse (current
, current
->sref
, current
->loc
);
10659 checkNumerics (ctype tr1
, ctype tr2
, ctype te1
, ctype te2
,
10660 /*@notnull@*/ exprNode e1
, /*@notnull@*/ exprNode e2
,
10665 if (!ctype_match (tr1
, tr2
))
10667 if ((ctype_isRealInt (tr1
) || ctype_isReal (tr1
)) &&
10668 (ctype_isRealInt (tr2
) || ctype_isReal (tr2
)))
10670 DPRINTF (("No error: [%s] %s / [%s] %s",
10671 exprNode_unparse (e1
), ctype_unparse (tr1
),
10672 exprNode_unparse (e2
), ctype_unparse (tr2
)));
10675 ** evans 2003-06-15: changed this so if either type is a literal,
10676 ** the other type is used.
10677 ** (Need to look at the ISO C99 rules on this...)
10680 if (exprNode_isNumLiteral (e1
)) {
10682 } else if (exprNode_isNumLiteral (e2
)) {
10685 ret
= ctype_biggerType (tr1
, tr2
);
10690 if (ctype_isNumAbstract (tr1
)
10691 && exprNode_isNumLiteral (e2
)
10692 && context_flagOn (FLG_NUMABSTRACTLIT
, e1
->loc
))
10694 ret
= tr1
; /* No error */
10696 else if (ctype_isNumAbstract (tr2
)
10697 && exprNode_isNumLiteral (e1
)
10698 && context_flagOn (FLG_NUMABSTRACTLIT
, e1
->loc
))
10706 message ("Incompatible types for %s (%s, %s): %s %s %s",
10707 lltok_unparse (op
),
10708 ctype_unparse (te1
),
10709 ctype_unparse (te2
),
10710 exprNode_unparse (e1
), lltok_unparse (op
),
10711 exprNode_unparse (e2
)),
10714 ret
= ctype_unknown
;
10718 ret
= ctype_biggerType (tr1
, tr2
);
10725 if (ctype_isNumAbstract (tr1
))
10729 else if (ctype_isForceRealNumeric (&tr1
)
10730 && ctype_isForceRealNumeric (&tr2
))
10732 ret
= ctype_resolveNumerics (tr1
, tr2
);
10734 else if (!context_msgStrictOps ())
10736 if (ctype_isPointer (tr1
))
10738 if (ctype_isPointer (tr2
) && !exprNode_isNullValue (e2
))
10742 else if (ctype_isInt (tr2
))
10748 ret
= ctype_unknown
;
10751 else if (ctype_isPointer (tr2
))
10753 if (ctype_isPointer (tr1
))
10757 else if (ctype_isInt (tr1
))
10763 ret
= ctype_unknown
;
10768 ret
= ctype_resolveNumerics (tr1
, tr2
);
10773 int opid
= lltok_getTok (op
);
10774 bool comparop
= (opid
== EQ_OP
|| opid
== NE_OP
10775 || opid
== TLT
|| opid
== TGT
10776 || opid
== LE_OP
|| opid
== GE_OP
);
10778 if (!ctype_isNumeric (tr1
) && !ctype_isNumeric (tr2
))
10781 && ((ctype_isEnum (tr1
) && ctype_isEnum (tr2
))
10782 || (ctype_isBool (tr1
) && ctype_isBool (tr2
))
10783 || (ctype_isChar (tr1
) && ctype_isChar (tr2
))))
10789 if (ctype_sameName (te1
, te2
))
10793 message ("Operands of %s are non-numeric (%t): %s %s %s",
10794 lltok_unparse (op
), te1
,
10795 exprNode_unparse (e1
), lltok_unparse (op
),
10796 exprNode_unparse (e2
)),
10803 message ("Operands of %s are non-numerics (%t, %t): %s %s %s",
10804 lltok_unparse (op
), te1
, te2
,
10805 exprNode_unparse (e1
), lltok_unparse (op
),
10806 exprNode_unparse (e2
)),
10811 else if (!ctype_isNumeric (tr1
))
10815 message ("Right operand of %s is non-numeric (%t): %s %s %s",
10816 lltok_unparse (op
), te1
,
10817 exprNode_unparse (e1
), lltok_unparse (op
),
10818 exprNode_unparse (e2
)),
10823 if (!ctype_isNumeric (tr2
))
10827 message ("Left operand of %s is non-numeric (%t): %s %s %s",
10828 lltok_unparse (op
), te2
,
10829 exprNode_unparse (e1
), lltok_unparse (op
),
10830 exprNode_unparse (e2
)),
10835 ret
= ctype_unknown
;
10843 abstractOpError (ctype tr1
, ctype tr2
, lltok op
,
10844 /*@notnull@*/ exprNode e1
, /*@notnull@*/ exprNode e2
,
10845 fileloc loc1
, fileloc loc2
)
10847 if (ctype_isRealAbstract (tr1
) && ctype_isRealAbstract (tr2
))
10849 if (ctype_match (tr1
, tr2
))
10851 if (ctype_isRealNumAbstract (tr1
))
10853 ; /* No warning for numabstract types */
10857 if (lltok_isEqOp (op
) || lltok_isNotEqOp (op
))
10860 (FLG_ABSTRACTCOMPARE
,
10861 message ("Object equality comparison (%s) on objects of abstract type (%t): %s %s %s",
10862 lltok_unparse (op
), tr1
,
10863 exprNode_unparse (e1
), lltok_unparse (op
), exprNode_unparse (e2
)),
10870 message ("Operands of %s are abstract type (%t): %s %s %s",
10871 lltok_unparse (op
), tr1
,
10872 exprNode_unparse (e1
), lltok_unparse (op
), exprNode_unparse (e2
)),
10879 if (ctype_isRealNumAbstract (tr1
) && ctype_isRealNumAbstract (tr2
))
10884 ("Operands of %s are different numabstract types (%t, %t): %s %s %s",
10885 lltok_unparse (op
), tr1
, tr2
,
10886 exprNode_unparse (e1
),
10887 lltok_unparse (op
), exprNode_unparse (e2
)),
10894 message ("Operands of %s are abstract types (%t, %t): %s %s %s",
10895 lltok_unparse (op
), tr1
, tr2
,
10896 exprNode_unparse (e1
), lltok_unparse (op
),
10897 exprNode_unparse (e2
)),
10902 else if (ctype_isRealAbstract (tr1
) && !ctype_isRealNumAbstract (tr1
))
10906 message ("Left operand of %s is abstract type (%t): %s %s %s",
10907 lltok_unparse (op
), tr1
,
10908 exprNode_unparse (e1
), lltok_unparse (op
), exprNode_unparse (e2
)),
10913 if (ctype_isRealAbstract (tr2
) && !ctype_isRealNumAbstract (tr2
))
10917 message ("Right operand of %s is abstract type (%t): %s %s %s",
10918 lltok_unparse (op
), tr2
,
10919 exprNode_unparse (e1
), lltok_unparse (op
), exprNode_unparse (e2
)),
10930 ** requies e1 and e2 and not error exprNode's.
10934 ** If e1 is a component of an abstract type, and e2 is mutable and client-visible,
10935 ** the rep of the abstract type is exposed.
10937 ** The order is very important:
10939 ** check rep expose (move into check transfer)
10945 ** This isn't really a sensible procedure, but the indententation
10946 ** was getting too deep.
10950 checkOneRepExpose (sRef ysr
, sRef base
,
10951 /*@notnull@*/ exprNode e1
,
10952 /*@notnull@*/ exprNode e2
, ctype ct
,
10955 if (!(sRef_isOnly (ysr
) || sRef_isKeep (ysr
)
10956 || sRef_isOwned (ysr
)
10957 || sRef_isExposed (ysr
)))
10959 if (sRef_isAnyParam (base
) && !sRef_isExposed (base
)
10960 && !sRef_isObserver (base
)) /* evans 2001-07-11: added isObserver */
10963 if (sRef_isIReference (ysr
))
10965 if (sRef_sameName (base
, sRef_getRootBase (e2
->sref
)))
10970 ("Assignment of mutable component of parameter %q "
10971 "to component of abstract "
10972 "type %s exposes rep: %s = %s",
10973 sRef_unparse (base
),
10974 ctype_unparse (ct
),
10975 exprNode_unparse (e1
), exprNode_unparse (e2
)),
10983 ("Assignment of mutable component of parameter %q "
10984 "(through alias %q) to component of abstract "
10985 "type %s exposes rep: %s = %s",
10986 sRef_unparse (base
),
10987 sRef_unparse (e2
->sref
),
10988 ctype_unparse (ct
),
10989 exprNode_unparse (e1
), exprNode_unparse (e2
)),
10995 if (sRef_sameName (base
, sRef_getRootBase (e2
->sref
)))
10999 message ("Assignment of mutable parameter %q "
11000 "to component of abstract type %s "
11001 "exposes rep: %s = %s",
11002 sRef_unparse (base
),
11003 ctype_unparse (ct
),
11004 exprNode_unparse (e1
),
11005 exprNode_unparse (e2
)),
11012 message ("Assignment of mutable parameter %q "
11013 "(through alias %q) to "
11014 "component of abstract type %s exposes "
11016 sRef_unparse (base
),
11017 sRef_unparse (e2
->sref
),
11018 ctype_unparse (ct
),
11019 exprNode_unparse (e1
),
11020 exprNode_unparse (e2
)),
11026 if (sRef_isFileOrGlobalScope (s2b
))
11028 if (sRef_sameName (base
, sRef_getRootBase (e2
->sref
)))
11032 message ("Assignment of global %q "
11034 "abstract type %s exposes rep: %s = %s",
11035 sRef_unparse (base
),
11036 ctype_unparse (ct
),
11037 exprNode_unparse (e1
), exprNode_unparse (e2
)),
11044 message ("Assignment of global %q (through alias %q) "
11046 "abstract type %s exposes rep: %s = %s",
11047 sRef_unparse (base
),
11048 sRef_unparse (e2
->sref
),
11049 ctype_unparse (ct
),
11050 exprNode_unparse (e1
), exprNode_unparse (e2
)),
11058 doAssign (/*@notnull@*/ exprNode e1
, /*@notnull@*/ exprNode e2
, bool isInit
)
11060 DPRINTF (("Do assign: %s <- %s",
11061 exprNode_unparse (e1
), exprNode_unparse (e2
)));
11062 DPRINTF (("Ctype: %s", ctype_unparse (exprNode_getType (e1
))));
11064 if (ctype_isRealFunction (exprNode_getType (e1
))
11065 && !ctype_isRealPointer (exprNode_getType (e1
)))
11069 message ("Invalid left-hand side of assignment (function type %s): %s",
11070 ctype_unparse (exprNode_getType (e1
)),
11071 exprNode_unparse (e1
)),
11075 if (context_getFlag (FLG_ASSIGNEXPOSE
) && ctype_isMutable (e2
->typ
))
11077 ctype t2
= exprNode_getType (e2
);
11078 sRef sr
= sRef_getRootBase (e1
->sref
);
11079 ctype ct
= sRef_getType (sr
);
11081 if (ctype_isAbstract (t2
)
11082 && !ctype_isNumAbstract (t2
)
11083 && !(uentry_isMutableDatatype (usymtab_getTypeEntry (ctype_typeId (t2
)))))
11085 /* it is immutable, okay to reference */
11086 goto donerepexpose
;
11089 if (ctype_isAbstract (ct
) && sRef_isIReference (e1
->sref
))
11091 sRef s2b
= sRef_getRootBase (e2
->sref
);
11092 sRef s1
= e1
->sref
;
11093 sRef s1b
= sRef_getRootBase (s1
);
11096 aliases
= usymtab_canAlias (e2
->sref
);
11098 if (!sRef_similar (s2b
, s1b
)
11099 && !sRef_isExposed (s1
)
11100 && !(sRef_isOnly (s2b
) || sRef_isKeep (s2b
) || sRef_isExposed (s2b
)))
11102 if (sRef_isAnyParam (s2b
) && !sRef_isOnly (s2b
)
11103 && !sRef_isOwned (s2b
) && !sRef_isKeep (s2b
)
11104 && !sRef_isExposed (s2b
))
11106 if (sRef_isIReference (e2
->sref
))
11111 ("Assignment of mutable component of parameter %q "
11112 "to component of abstract type %s exposes rep: %s = %s",
11113 sRef_unparse (s2b
),
11114 ctype_unparse (ct
),
11115 exprNode_unparse (e1
), exprNode_unparse (e2
)),
11122 message ("Assignment of mutable parameter %q to "
11123 "component of abstract type %s exposes rep: %s = %s",
11124 sRef_unparse (s2b
),
11125 ctype_unparse (ct
),
11126 exprNode_unparse (e1
), exprNode_unparse (e2
)),
11131 if (sRef_isFileOrGlobalScope (s2b
))
11135 message ("Assignment of global %q to component of "
11136 "abstract type %s exposes rep: %s = %s",
11137 sRef_unparse (s2b
),
11138 ctype_unparse (ct
),
11139 exprNode_unparse (e1
), exprNode_unparse (e2
)),
11143 sRefSet_realElements (aliases
, ysr
)
11145 sRef base
= sRef_getRootBase (ysr
);
11147 if (sRef_similar (ysr
, s2b
) || sRef_similar (s1b
, base
)
11148 || sRef_sameName (base
, s1b
))
11150 ; /* error already reported or same sref */
11154 checkOneRepExpose (ysr
, base
, e1
, e2
, ct
, s2b
);
11156 } end_sRefSet_realElements
;
11158 sRefSet_free (aliases
);
11165 ** function variables don't really work...
11168 if (!ctype_isFunction (ctype_realType (e2
->typ
)))
11172 DPRINTF (("Check init: %s / %s",
11173 exprNode_unparse (e1
), exprNode_unparse (e2
)));
11174 transferChecks_initialization (e1
, e2
);
11178 transferChecks_assign (e1
, e2
);
11183 sRef fref
= e2
->sref
;
11185 sRef_setDefState (e1
->sref
, sRef_getDefState (fref
), e1
->loc
);
11186 sRef_setNullState (e1
->sref
, sRef_getNullState (fref
), e1
->loc
);
11188 /* Need to typecheck the annotation on the parameters */
11190 if (ctype_isRealFunction (e1
->typ
)) {
11191 uentryList e1p
= ctype_argsFunction (ctype_realType (e1
->typ
));
11192 uentryList e2p
= ctype_argsFunction (ctype_realType (e2
->typ
));
11194 if (!uentryList_isMissingParams (e1p
)
11195 && !uentryList_isMissingParams (e2p
)
11196 && uentryList_size (e1p
) > 0) {
11197 if (uentryList_size (e1p
) == uentryList_size (e2p
)) {
11200 uentryList_elements (e1p
, el1
) {
11203 el2
= uentryList_getN (e2p
, n
);
11205 uentry_checkMatchParam (el1
, el2
, n
, e2
);
11206 } end_uentryList_elements
;
11212 if (exprNode_isStringLiteral (e2
))
11214 exprNode_checkStringLiteralLength (exprNode_getType (e1
), e2
);
11217 if (isInit
&& sRef_isFileOrGlobalScope (e1
->sref
))
11223 DPRINTF (("Update aliases: %s / %s", exprNode_unparse (e1
), exprNode_unparse (e2
)));
11224 updateAliases (e1
, e2
);
11229 checkMacroParen (exprNode e
)
11231 if (exprNode_isError (e
) || e
->kind
== XPR_CAST
)
11237 if (sRef_isUnsafe (e
->sref
) && !exprNode_isInParens (e
))
11241 message ("Macro parameter used without parentheses: %s",
11242 exprNode_unparse (e
)),
11249 reflectNullTest (/*@notnull@*/ exprNode e
, bool isnull
)
11253 e
->guards
= guardSet_addTrueGuard (e
->guards
, e
->sref
);
11257 e
->guards
= guardSet_addFalseGuard (e
->guards
, e
->sref
);
11264 ** if e2 is a parameter or global derived location which
11265 ** can be modified (that is, e2 is a mutable abstract type,
11266 ** or a derived pointer), then e1 can alias e2.
11268 ** e1 can alias everything which e2 can alias.
11270 ** Also, if e1 is guarded, remove from guard sets!
11273 static void updateAliases (/*@notnull@*/ exprNode e1
, /*@notnull@*/ exprNode e2
)
11275 if (!context_inProtectVars ())
11278 ** depends on types of e1 and e2
11281 sRef s1
= e1
->sref
;
11282 sRef s2
= e2
->sref
;
11283 ctype t1
= exprNode_getType (e1
);
11285 /* handle pointer sRefs, record fields, arrays, etc... */
11287 if (!ctype_isRealSU (t1
))
11289 DPRINTF (("Copying real! %s", ctype_unparse (t1
)));
11290 sRef_copyRealDerivedComplete (s1
, s2
);
11295 ** Fields should alias
11298 DPRINTF (("Not COPYING!: %s", ctype_unparse (t1
)));
11301 if (ctype_isMutable (t1
) && sRef_isKnown (s1
))
11303 usymtab_clearAlias (s1
);
11304 usymtab_addMustAlias (s1
, s2
);
11305 DPRINTF (("Add must alias: %s / %s", sRef_unparse (s1
), sRef_unparse (s2
)));
11309 DPRINTF (("Not mutable: %s", ctype_unparse (t1
)));
11312 if (sRef_possiblyNull (s1
) && usymtab_isGuarded (s1
))
11314 usymtab_unguard (s1
);
11319 exprNode
exprNode_updateLocation (/*@returned@*/ exprNode e
, /*@temp@*/ fileloc loc
)
11321 if (exprNode_isDefined (e
))
11323 e
->loc
= fileloc_update (e
->loc
, loc
);
11327 e
= exprNode_createLoc (ctype_unknown
, fileloc_copy (loc
));
11333 static void checkUniqueParams (exprNode fcn
,
11334 /*@notnull@*/ exprNode current
,
11336 int paramno
, uentry ucurrent
)
11339 sRef thisref
= exprNode_getSref (current
);
11342 ** Check if any argument could match this argument.
11345 exprNodeList_elements (args
, icurrent
)
11349 if (iparamno
!= paramno
)
11351 sRef sr
= exprNode_getSref (icurrent
);
11353 if (sRef_similarRelaxed (thisref
, sr
))
11355 if (!sRef_isConst (thisref
) && !sRef_isConst (sr
))
11360 ("Parameter %d (%s) to function %s is declared %s but "
11361 "is aliased by parameter %d (%s)",
11363 exprNode_unparse (current
),
11364 exprNode_unparse (fcn
),
11365 alkind_unparse (uentry_getAliasKind (ucurrent
)),
11366 iparamno
, exprNode_unparse (icurrent
)),
11372 sRefSet aliases
= usymtab_canAlias (sr
);
11374 sRefSet_allElements (aliases
, asr
)
11376 if (ctype_isUnknown (sRef_getType (thisref
)))
11378 sRef_setType (thisref
, uentry_getType (ucurrent
));
11381 if (sRef_similarRelaxed (thisref
, asr
))
11383 if (sRef_isExternal (asr
))
11385 if (sRef_isLocalState (thisref
))
11391 sRef base
= sRef_getRootBase (asr
);
11393 if (!sRef_similar (sRef_getBase (asr
), thisref
))
11395 if (sRef_isUnique (base
) || sRef_isOnly (base
)
11396 || sRef_isKept (base
)
11397 || (sRef_isAddress (asr
) && sRef_isLocalVar (base
))
11398 || (sRef_isAddress (thisref
)
11399 && sRef_isLocalVar (sRef_getRootBase (thisref
))))
11401 ; /* okay, no error */
11406 (FLG_MAYALIASUNIQUE
,
11408 ("Parameter %d (%s) to function %s is declared %s but "
11409 "may be aliased externally by parameter %d (%s)",
11411 exprNode_unparse (current
),
11412 exprNode_unparse (fcn
),
11413 alkind_unparse (uentry_getAliasKind (ucurrent
)),
11414 iparamno
, exprNode_unparse (icurrent
)),
11425 ("Parameter %d (%s) to function %s is declared %s but "
11426 "is aliased externally by parameter %d (%s) through "
11429 exprNode_unparse (current
),
11430 exprNode_unparse (fcn
),
11431 alkind_unparse (uentry_getAliasKind (ucurrent
)),
11432 iparamno
, exprNode_unparse (icurrent
),
11433 sRef_unparse (asr
)),
11437 } end_sRefSet_allElements
;
11438 sRefSet_free (aliases
);
11441 } end_exprNodeList_elements
;
11444 long exprNode_getLongValue (exprNode e
)
11448 if (exprNode_hasValue (e
) && multiVal_isInt (exprNode_getValue (e
)))
11450 value
= multiVal_forceInt (exprNode_getValue (e
));
11454 value
= 0; /* Unknown value */
11460 /*@only@*/ fileloc
exprNode_getNextSequencePoint (exprNode e
)
11463 ** Returns the location of the sequence point following e.
11465 ** Only works for statements (for now).
11468 if (exprNode_isDefined (e
) && e
->kind
== XPR_STMT
) {
11469 lltok t
= exprData_getUopTok (e
->edata
);
11470 return fileloc_copy(lltok_getLoc (t
));
11472 /* drl possible problem : warning fix
11473 llcontbug (message ("Cannot get next sequence point: %s", exprNode_unparse (e)));
11475 return fileloc_undefined
;
11479 exprNode
exprNode_createNew(ctype c
)
11483 ret
= exprNode_createPlain (c
);
11488 bool exprNode_isInitBlock (exprNode e
)
11490 return (exprNode_isDefined(e
) && e
->kind
== XPR_INITBLOCK
);
11493 /*drl 3/2/2003 moved this function out of constraint.c */
11494 exprNode
exprNode_copyConstraints (/*@returned@*/ exprNode dst
, exprNode src
)
11497 llassert (exprNode_isDefined (dst
) );
11498 llassert (exprNode_isDefined (src
) );
11500 constraintList_free (dst
->ensuresConstraints
);
11501 constraintList_free (dst
->requiresConstraints
);
11502 constraintList_free (dst
->trueEnsuresConstraints
);
11503 constraintList_free (dst
->falseEnsuresConstraints
);
11505 dst
->ensuresConstraints
= constraintList_copy (src
->ensuresConstraints
);
11506 dst
->requiresConstraints
= constraintList_copy (src
->requiresConstraints
);
11507 dst
->trueEnsuresConstraints
= constraintList_copy (src
->trueEnsuresConstraints
);
11508 dst
->falseEnsuresConstraints
= constraintList_copy (src
->falseEnsuresConstraints
);
11512 void exprNode_revealState (exprNode e
)
11514 if (exprNode_isDefined (e
)) {
11515 llmsg (message ("%s: State of %s: %s", fileloc_unparse (exprNode_loc (e
)),
11516 exprNode_unparse (e
), sRef_unparseFull (e
->sref
)));
11518 llmsg (message ("%s: Reveal state undefined", fileloc_unparse (g_currentloc
)));