]> andersk Git - splint.git/blame - src/exprNode.c
*** empty log message ***
[splint.git] / src / exprNode.c
CommitLineData
616915dd 1/*
2** LCLint - annotation-assisted static program checker
28bf4b0b 3** Copyright (C) 1994-2001 University of Virginia,
616915dd 4** Massachusetts Institute of Technology
5**
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.
10**
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.
15**
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.
19**
20** For information on lclint: lclint-request@cs.virginia.edu
21** To report a bug: lclint-bug@cs.virginia.edu
22** For more information: http://lclint.cs.virginia.edu
23*/
24/*
25** exprNode.c
26*/
27
28# include <ctype.h> /* for isdigit */
29# include "lclintMacros.nf"
30# include "basic.h"
31# include "cgrammar.h"
32# include "cgrammar_tokens.h"
33
34# include "exprChecks.h"
28bf4b0b 35# include "transferChecks.h"
616915dd 36# include "exprNodeSList.h"
616915dd 37
38static bool exprNode_isEmptyStatement (exprNode p_e);
39static /*@exposed@*/ exprNode exprNode_firstStatement (/*@returned@*/ exprNode p_e);
40static bool exprNode_isFalseConstant (exprNode p_e) /*@*/ ;
41static bool exprNode_isBlock (exprNode p_e);
42static void checkGlobUse (uentry p_glob, bool p_isCall, /*@notnull@*/ exprNode p_e);
28bf4b0b 43static void exprNode_addUse (exprNode p_e, /*@exposed@*/ sRef p_s);
616915dd 44static bool exprNode_matchArgType (ctype p_ct, exprNode p_e);
28bf4b0b 45static exprNode exprNode_fakeCopy (exprNode p_e) /*@*/ ;
616915dd 46static exprNode exprNode_statementError (/*@only@*/ exprNode p_e, /*@only@*/ lltok p_t);
47static bool exprNode_matchTypes (exprNode p_e1, exprNode p_e2);
48static void checkUniqueParams (exprNode p_fcn,
49 /*@notnull@*/ exprNode p_current, exprNodeList p_args,
50 int p_paramno, uentry p_ucurrent);
51static void updateAliases (/*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2);
52static void abstractOpError (ctype p_tr1, ctype p_tr2, lltok p_op,
53 /*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2,
54 fileloc p_loc1, fileloc p_loc2);
55static ctype checkNumerics (ctype p_tr1, ctype p_tr2, ctype p_te1, ctype p_te2,
56 /*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2, lltok p_op);
57static void doAssign (/*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2, bool p_isInit);
28bf4b0b 58static void checkSafeUse (exprNode p_e, /*@exposed@*/ sRef p_s);
616915dd 59static void reflectNullTest (/*@notnull@*/ exprNode p_e, bool p_isnull);
60static void checkMacroParen (exprNode p_e);
61static exprNodeSList exprNode_flatten (/*@dependent@*/ exprNode p_e);
62static void exprNode_checkSetAny (exprNode p_e, /*@dependent@*/ cstring p_name);
28bf4b0b 63static void exprNode_checkUse (exprNode p_e, /*@exposed@*/ sRef p_s, fileloc p_loc);
616915dd 64static void exprNode_mergeUSs (exprNode p_res, exprNode p_other);
65static void exprNode_mergeCondUSs (exprNode p_res, exprNode p_other1, exprNode p_other2);
66static /*@only@*/ /*@notnull@*/ exprNode exprNode_fromIdentifierAux (/*@observer@*/ uentry p_c);
67static void checkAnyCall (/*@notnull@*/ /*@dependent@*/ exprNode p_fcn,
68 /*@dependent@*/ cstring p_fname,
69 uentryList p_pn, exprNodeList p_args,
70 bool p_hasMods, sRefSet p_mods, bool p_isSpec,
71 int p_specialArgs);
72static void checkOneArg (uentry p_ucurrent, /*@notnull@*/ exprNode p_current,
73 /*@dependent@*/ exprNode p_fcn, bool p_isSpec, int p_argno, int p_totargs);
74static void
75 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode p_fcn, uentryList p_params, exprNodeList p_args);
76
77static /*@only@*/ exprNode exprNode_effect (exprNode p_e)
78 /*@globals internalState@*/ ;
79static /*@only@*/ cstring exprNode_doUnparse (exprNode p_e);
80static /*@observer@*/ cstring exprNode_rootVarName (exprNode p_e);
81static /*@exposed@*/ exprNode
82 exprNode_lastStatement (/*@returned@*/ exprNode p_e);
83
84static /*@null@*/ sRef defref = sRef_undefined;
85static /*@only@*/ exprNode mustExitNode = exprNode_undefined;
86
87static int checkArgsReal (uentry p_fcn, /*@dependent@*/ exprNode p_f,
88 uentryList p_cl,
89 exprNodeList p_args, bool p_isIter, exprNode p_ret);
90
91static bool inEffect = FALSE;
92static int nowalloc = 0;
93static int totalloc = 0;
94static int maxalloc = 0;
95
96static /*@only@*/ uentry regArg;
97static /*@only@*/ uentry outArg;
98static /*@only@*/ uentry outStringArg;
99static /*@exposed@*/ sRef stdinRef;
100static /*@exposed@*/ sRef stdoutRef;
101static /*@only@*/ uentry csArg;
102static /*@only@*/ uentry csOnlyArg;
103static ctype cstringType;
104static ctype ctypeType;
105static ctype filelocType;
106static bool initMod = FALSE;
107
ccf0a4a8 108/*@function void exprNode_swap (sef exprNode, sef exprNode)@*/
109/*@-macroassign@*/
110# define exprNode_swap(e1,e2) do { exprNode m_tmp = (e1); (e1) = (e2); (e2) = m_tmp; } while (FALSE)
111/*@=macroassign@*/
112
08eb3d0e 113static void exprNode_defineConstraints(/*@sef@*/ /*@special@*/ /*@notnull@*/ exprNode e)
114 /*@defines e->requiresConstraints, e->ensuresConstraints,
115 e->trueEnsuresConstraints, e->falseEnsuresConstraints @*/
116{
117 e->requiresConstraints = constraintList_makeNew ();
118 e->ensuresConstraints = constraintList_makeNew ();
119 e->trueEnsuresConstraints = constraintList_makeNew ();
120 e->falseEnsuresConstraints = constraintList_makeNew ();
121}
84c9ffbf 122
616915dd 123/*
124** must occur after library has been read
125*/
126
127void exprNode_initMod (void)
128 /*@globals undef regArg, undef outArg, undef outStringArg,
129 undef csOnlyArg, undef csArg;
130 @*/
131{
132 uentry ue;
133 idDecl tmp;
134
135 initMod = TRUE;
136 cstringType = ctype_unknown;
137 ctypeType = ctype_unknown;
138 filelocType = ctype_unknown;
139
140 defref = sRef_undefined;
141
142 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
143 {
144 cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
145 }
146
147 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
148 {
149 ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
150 }
151
152 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
153 {
154 filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
155 }
156
157 if (usymtab_existsGlob (cstring_makeLiteralTemp ("stdin")))
158 {
159 ue = usymtab_lookupGlob (cstring_makeLiteralTemp ("stdin"));
160 }
161 else /* define stdin */
162 {
163 ue = uentry_makeVariable (cstring_makeLiteralTemp ("stdin"),
164 ctype_unknown,
165 fileloc_getBuiltin (),
166 FALSE);
167 uentry_setHasNameError (ue);
168 ue = usymtab_supGlobalEntryReturn (ue);
169 }
170
171 stdinRef = sRef_makePointer (uentry_getSref (ue));
172
173 if (usymtab_existsGlob (cstring_makeLiteralTemp ("stdout")))
174 {
175 ue = usymtab_lookupGlob (cstring_makeLiteralTemp ("stdout"));
176 }
177 else
178 {
179 ue = uentry_makeVariable (cstring_makeLiteralTemp ("stdout"),
180 ctype_unknown,
181 fileloc_getBuiltin (),
182 FALSE);
183 uentry_setHasNameError (ue);
184 ue = usymtab_supGlobalEntryReturn (ue);
185 }
186
187 stdoutRef = sRef_makePointer (uentry_getSref (ue));
188
189 tmp = idDecl_create (cstring_undefined, qtype_create (ctype_unknown));
190
191 regArg = uentry_makeParam (tmp, PARAMUNKNOWN);
192
193 idDecl_setTyp (tmp,
194 qtype_addQual (qtype_create (ctype_makePointer (ctype_unknown)),
195 qual_createOut ()));
196
197 outArg = uentry_makeParam (tmp, PARAMUNKNOWN);
198
199 idDecl_setTyp (tmp, qtype_addQual (qtype_create (ctype_string),
200 qual_createOut ()));
201
202 outStringArg = uentry_makeParam (tmp, PARAMUNKNOWN);
203
204 idDecl_setTyp (tmp, qtype_addQual (qtype_addQual (qtype_create (cstringType),
205 qual_createOnly ()),
206 qual_createNull ()));
207
208 csOnlyArg = uentry_makeParam (tmp, PARAMUNKNOWN);
209
210 idDecl_setTyp (tmp, qtype_addQual (qtype_create (cstringType), qual_createNull ()));
211 csArg = uentry_makeParam (tmp, PARAMUNKNOWN);
212
213 idDecl_free (tmp);
214}
215
216void
217exprNode_destroyMod (void)
218 /*@globals killed regArg, killed outArg, killed outStringArg,
219 killed mustExitNode, initMod @*/
220{
221 if (initMod)
222 {
223 uentry_free (regArg);
224 uentry_free (outArg);
225 uentry_free (outStringArg);
226
227 exprNode_free (mustExitNode);
228 initMod = FALSE;
229 /*@-branchstate@*/
230 }
231 /*@=branchstate@*/
232}
233
234static void exprNode_resetSref (/*@notnull@*/ exprNode e)
235{
236 e->sref = defref;
237}
238
28bf4b0b 239exprNode exprNode_fakeCopy (exprNode e)
240{
241 /*@-temptrans@*/ /*@-retalias@*/
242 return e;
243 /*@=temptrans@*/ /*@=retalias@*/
244}
245
616915dd 246static bool isFlagKey (char key)
247{
248 return (key == '-' || key == '+' || key == ' ' || key == '#');
249}
250
251static void exprNode_combineControl (/*@notnull@*/ exprNode ret,
252 /*@notnull@*/ exprNode ifclause,
253 /*@notnull@*/ exprNode elseclause)
254{
255 ret->canBreak = ifclause->canBreak || elseclause->canBreak;
256
257 ret->mustBreak =
258 (ifclause->mustBreak || exprNode_mustEscape (ifclause))
259 && (elseclause->mustBreak || exprNode_mustEscape (elseclause));
260
261 ret->exitCode = exitkind_combine (ifclause->exitCode,
262 elseclause->exitCode);
263
264}
265
266/*
267** For exprNode's returned by exprNode_effect.
268*/
269
270static bool shallowKind (exprKind kind)
271{
272 return (kind == XPR_STRINGLITERAL
273 || kind == XPR_NUMLIT
274 || kind == XPR_EMPTY
275 || kind == XPR_BODY
276 || kind == XPR_NODE);
277}
278
279static void
280exprNode_freeIniter (/*@only@*/ exprNode e)
281{
282 if (!exprNode_isError (e))
283 {
284 switch (e->kind)
285 {
286 case XPR_FACCESS:
28bf4b0b 287 /*
288 ** Its a fake copy, don't free the field->rec and field->field
289 ** fields.
290 */
291
292 /*@-compdestroy@*/
616915dd 293 sfree (e->edata->field);
28bf4b0b 294 /*@=compdestroy@*/
295
616915dd 296 sfree (e->edata);
297 break;
298 case XPR_FETCH:
299 exprNode_free (e->edata->op->b);
300 /*@-compdestroy@*/ sfree (e->edata->op); /*@=compdestroy@*/
301 sfree (e->edata);
302 break;
303 default:
304 llbug (message ("other: %s", exprNode_unparse (e)));
305 }
306
307 multiVal_free (e->val);
308 cstring_free (e->etext);
309 fileloc_free (e->loc);
310 sRefSet_free (e->uses);
311 sRefSet_free (e->sets);
312 sRefSet_free (e->msets);
313 guardSet_free (e->guards);
bb25bea6 314
315 constraintList_free(e->requiresConstraints);
316 constraintList_free(e->ensuresConstraints);
317 constraintList_free(e->trueEnsuresConstraints);
318 constraintList_free(e->falseEnsuresConstraints);
319
320 e->requiresConstraints = NULL;
321 e->ensuresConstraints = NULL;
322 e->trueEnsuresConstraints = NULL;
323 e->falseEnsuresConstraints = NULL;
324
616915dd 325 sfree (e);
326 }
327}
328
329void
330exprNode_freeShallow (/*@only@*/ exprNode e)
331{
332 if (!exprNode_isError (e))
333 {
334 if (shallowKind (e->kind))
335 {
336 }
337 else
338 {
339 if (!inEffect)
340 {
341 if (e->kind == XPR_EMPTY
342 || e->kind == XPR_BODY
343 || e->kind == XPR_STRINGLITERAL
344 || e->kind == XPR_NUMLIT
345 || e->kind == XPR_NODE
346 || e->kind == XPR_OFFSETOF
347 || e->kind == XPR_ALIGNOFT
348 || e->kind == XPR_ALIGNOF
349 || e->kind == XPR_SIZEOFT
350 || e->kind == XPR_SIZEOF)
351 {
352 /* don't free anything */
353 }
354 else
355 {
356 /* multiVal_free (e->val); */
357 cstring_free (e->etext);
358 fileloc_free (e->loc);
359 sRefSet_free (e->uses);
360 sRefSet_free (e->sets);
361 sRefSet_free (e->msets);
362 guardSet_free (e->guards);
363 exprData_freeShallow (e->edata, e->kind);
364 nowalloc--;
365 /*@-compdestroy@*/ sfree (e); /*@=compdestroy@*/
366 /*@-branchstate@*/
367 }
368 }
369 } /*@=branchstate@*/
370 }
371 }
372
373void
374exprNode_free (exprNode e)
375{
376 if (!exprNode_isError (e))
377 {
378 if (!inEffect)
379 {
380 multiVal_free (e->val);
381 cstring_free (e->etext);
382 fileloc_free (e->loc);
383 sRefSet_free (e->uses);
384 sRefSet_free (e->sets);
385 sRefSet_free (e->msets);
386 guardSet_free (e->guards);
387 exprData_free (e->edata, e->kind);
388
bb25bea6 389 constraintList_free(e->requiresConstraints);
390 constraintList_free(e->ensuresConstraints);
391 constraintList_free(e->trueEnsuresConstraints);
392 constraintList_free(e->falseEnsuresConstraints);
393
394 e->requiresConstraints = NULL;
395 e->ensuresConstraints = NULL;
396 e->trueEnsuresConstraints = NULL;
397 e->falseEnsuresConstraints = NULL;
398
616915dd 399 nowalloc--;
400 sfree (e);
401 /*@-branchstate@*/
402 } /*@=branchstate@*/
403 }
404}
405
406exprNode
407exprNode_makeError ()
408{
409 return exprNode_undefined;
410}
411
412static /*@out@*/ /*@only@*/ /*@notnull@*/ exprNode
413exprNode_new (void)
414{
415 exprNode ret = (exprNode) dmalloc (sizeof (*ret));
416 /* static int lastexpnodes = 0; */
417
418 nowalloc++;
419 totalloc++;
420
421 if (nowalloc > maxalloc)
422 {
423 maxalloc = nowalloc;
424 }
425
426 return ret;
427}
428
429static /*@notnull@*/ /*@special@*/ exprNode
430 exprNode_createPlain (ctype c)
431 /*@defines result@*/
28bf4b0b 432 /*@ensures isnull result->edata, result->loc, result->val, result->guards,
433 result->uses, result->sets, result->msets, result->etext @*/
616915dd 434 /*@*/
435{
436 exprNode e = exprNode_new ();
437
438 e->typ = c;
439 e->kind = XPR_EMPTY;
440 e->val = multiVal_undefined;
441 e->sref = defref;
442 e->etext = cstring_undefined;
443 e->loc = fileloc_undefined;
444 e->guards = guardSet_undefined;
445 e->uses = sRefSet_undefined;
446 e->sets = sRefSet_undefined;
447 e->msets = sRefSet_undefined;
448 e->edata = exprData_undefined;
449 e->exitCode = XK_NEVERESCAPE;
450 e->canBreak = FALSE;
451 e->mustBreak = FALSE;
452 e->isJumpPoint = FALSE;
8ac07c2e 453
454 exprNode_defineConstraints(e);
455
616915dd 456 return (e);
457}
458
459/*@observer@*/ exprNode exprNode_makeMustExit (void)
460{
461 if (exprNode_isUndefined (mustExitNode))
462 {
463 mustExitNode = exprNode_createPlain (ctype_unknown);
464 mustExitNode->exitCode = XK_MUSTEXIT;
465 }
466
467 return mustExitNode;
468}
469
470
471static /*@notnull@*/ /*@special@*/ exprNode exprNode_create (ctype c)
472 /*@defines result@*/
473 /*@post:isnull result->edata, result->guards, result->val,
474 result->uses, result->sets, result->msets@*/
475 /*@*/
476{
477 exprNode e = exprNode_createPlain (c);
478 e->loc = fileloc_copy (g_currentloc);
479 return (e);
480}
481
482static /*@notnull@*/ /*@special@*/ exprNode exprNode_createUnknown (void)
483 /*@defines result@*/
484 /*@post:isnull result->edata, result->guards,
485 result->uses, result->sets, result->msets@*/
486 /*@*/
487{
488 return (exprNode_create (ctype_unknown));
489}
490
491static /*@notnull@*/ /*@special@*/ exprNode
492 exprNode_createLoc (ctype c, /*@keep@*/ fileloc loc)
493 /*@defines result@*/
494 /*@post:isnull result->edata, result->guards, result->val,
495 result->uses, result->sets, result->msets@*/
496 /*@*/
497{
498 exprNode e = exprNode_createPlain (c);
499 e->loc = loc;
500 return (e);
501}
502
503static void
504 exprNode_copySets (/*@special@*/ /*@notnull@*/ exprNode ret, exprNode e)
505 /*@defines ret->guards, ret->uses, ret->sets, ret->msets@*/
506{
507 if (exprNode_isDefined (e))
508 {
509 ret->guards = guardSet_copy (e->guards);
510 ret->uses = sRefSet_newCopy (e->uses);
511 ret->sets = sRefSet_newCopy (e->sets);
512 ret->msets = sRefSet_newCopy (e->msets);
513 }
514 else
515 {
516 ret->guards = guardSet_undefined;
517 ret->uses = sRefSet_undefined;
518 ret->sets = sRefSet_undefined;
519 ret->msets = sRefSet_undefined;
520 }
521}
522
523static /*@notnull@*/ /*@special@*/ exprNode
524 exprNode_createPartialLocCopy (exprNode e, /*@only@*/ fileloc loc)
525 /*@defines result@*/
526 /*@post:isnull result->edata, result->etext@*/
527 /*@*/
528{
529 exprNode ret = exprNode_new ();
530
531 if (exprNode_isError (e))
532 {
533 ret->typ = ctype_unknown;
534 ret->val = multiVal_undefined;
535 ret->loc = loc;
536 ret->guards = guardSet_undefined;
537 ret->uses = sRefSet_undefined;
538 ret->sets = sRefSet_undefined;
539 ret->msets = sRefSet_undefined;
540 }
541 else
542 {
543 ret->typ = e->typ;
544 ret->val = multiVal_copy (e->val);
545 ret->loc = loc;
546 ret->guards = guardSet_copy (e->guards);
547 ret->uses = sRefSet_newCopy (e->uses);
548 ret->sets = sRefSet_newCopy (e->sets);
549 ret->msets = sRefSet_newCopy (e->msets);
550 }
551
552 ret->kind = XPR_EMPTY;
553 ret->sref = defref;
554 ret->etext = cstring_undefined;
555 ret->exitCode = XK_NEVERESCAPE;
556 ret->canBreak = FALSE;
557 ret->mustBreak = FALSE;
558 ret->isJumpPoint = FALSE;
559 ret->edata = exprData_undefined;
560
bb25bea6 561 exprNode_defineConstraints(ret);
562
616915dd 563 return (ret);
564}
565
566
567static /*@notnull@*/ /*@special@*/ exprNode
568 exprNode_createPartialCopy (exprNode e)
569 /*@defines result@*/
570 /*@post:isnull result->edata, result->etext@*/
571 /*@*/
572{
573 return (exprNode_createPartialLocCopy (e, fileloc_copy (exprNode_loc (e))));
574}
575
576static /*@notnull@*/ /*@special@*/ exprNode
577 exprNode_createPartialNVCopy (exprNode e)
578 /*@defines result@*/
579 /*@post:isnull result->edata, result->etext, result->val @*/
580 /*@*/
581{
582 exprNode ret = exprNode_new ();
583
584 if (exprNode_isError (e))
585 {
586 ret->typ = ctype_unknown;
587 ret->loc = fileloc_undefined;
588 ret->guards = guardSet_undefined;
589 ret->uses = sRefSet_undefined;
590 ret->sets = sRefSet_undefined;
591 ret->msets = sRefSet_undefined;
592 }
593 else
594 {
595 ret->typ = e->typ;
596 ret->loc = fileloc_copy (e->loc);
597 ret->guards = guardSet_copy (e->guards);
598 ret->uses = sRefSet_newCopy (e->uses);
599 ret->sets = sRefSet_newCopy (e->sets);
600 ret->msets = sRefSet_newCopy (e->msets);
601 }
602
603 ret->val = multiVal_undefined;
604 ret->kind = XPR_EMPTY;
605 ret->sref = defref;
606 ret->etext = cstring_undefined;
607 ret->exitCode = XK_NEVERESCAPE;
608 ret->canBreak = FALSE;
609 ret->mustBreak = FALSE;
610 ret->isJumpPoint = FALSE;
611 ret->edata = exprData_undefined;
612
bb25bea6 613 exprNode_defineConstraints(ret);
614
616915dd 615 return (ret);
616}
617
618static /*@notnull@*/ /*@special@*/ exprNode
619 exprNode_createSemiCopy (exprNode e)
620 /*@defines result@*/
621 /*@post:isnull result->edata, result->etext, result->sets,
622 result->msets, result->uses, result->guards@*/
623 /*@*/
624{
625 if (exprNode_isError (e))
626 {
627 return exprNode_createPlain (ctype_unknown);
628 }
629 else
630 {
631 exprNode ret = exprNode_new ();
632
633 ret->typ = e->typ;
634 ret->val = multiVal_copy (e->val);
635 ret->loc = fileloc_copy (e->loc);
636 ret->guards = guardSet_undefined;
637 ret->uses = sRefSet_undefined;
638 ret->sets = sRefSet_undefined;
639 ret->msets = sRefSet_undefined;
640
641 ret->kind = XPR_EMPTY;
642 ret->sref = defref;
643 ret->etext = cstring_undefined;
644 ret->exitCode = XK_NEVERESCAPE;
645 ret->canBreak = FALSE;
646 ret->mustBreak = FALSE;
647 ret->isJumpPoint = FALSE;
648 ret->edata = exprData_undefined;
649
bb25bea6 650 exprNode_defineConstraints(ret);
651
616915dd 652 return (ret);
653 }
654}
655
656bool
657exprNode_isNullValue (exprNode e)
658{
659 if (exprNode_isDefined (e))
660 {
661 multiVal m = exprNode_getValue (e);
662
663 if (multiVal_isInt (m))
664 {
665 return (multiVal_forceInt (m) == 0);
666 }
667 }
668
669 return FALSE;
670}
671
672static bool
673exprNode_isUnknownConstant (/*@notnull@*/ exprNode e)
674{
675 while (e->kind == XPR_PARENS)
676 {
677 e = exprData_getUopNode (e->edata);
678 llassert (exprNode_isDefined (e));
679 }
680
681 if (e->kind == XPR_CONST)
682 {
683 multiVal m = exprNode_getValue (e);
684
685 if (multiVal_isUnknown (m))
686 {
687 return TRUE;
688 }
689 }
690
691 return FALSE;
692}
693
694/*@only@*/ exprNode
695 exprNode_numLiteral (ctype c, /*@temp@*/ cstring t,
696 /*@only@*/ fileloc loc, long val)
697{
698 exprNode e = exprNode_createLoc (c, loc);
699
700 e->kind = XPR_NUMLIT;
701
702 llassert (multiVal_isUndefined (e->val));
703 e->val = multiVal_makeInt (val);
704 e->edata = exprData_makeLiteral (cstring_copy (t));
705
706 if (val == 0)
707 {
708 e->sref = sRef_makeUnknown ();
709 sRef_setDefNull (e->sref, e->loc);
710 }
711
712 DPRINTF (("Num lit: %s / %s", exprNode_unparse (e), ctype_unparse (exprNode_getType (e))));
713 return (e);
714}
715
716/*@only@*/ exprNode
717exprNode_charLiteral (char c, cstring text, /*@only@*/ fileloc loc)
718{
719 exprNode e = exprNode_createLoc (ctype_char, loc);
720
721 if (context_getFlag (FLG_CHARINTLITERAL))
722 {
723 e->typ = ctype_makeConj (ctype_char, ctype_int);
724 }
725
726 e->kind = XPR_NUMLIT;
727 e->val = multiVal_makeChar (c);
728
729 e->edata = exprData_makeLiteral (cstring_copy (text));
730 return (e);
731}
732
733/*@only@*/ exprNode
734exprNode_floatLiteral (double d, ctype ct, cstring text, /*@only@*/ fileloc loc)
735{
736 exprNode e = exprNode_createLoc (ct, loc);
737
738 e->kind = XPR_NUMLIT;
739 e->val = multiVal_makeDouble (d);
740 e->edata = exprData_makeLiteral (cstring_copy (text));
741 return (e);
742}
743
744multiVal exprNode_getValue (exprNode e)
745{
746 while (exprNode_isInParens (e)) {
747 if (e->edata != NULL) {
748 e = exprData_getUopNode (e->edata);
749 } else {
750 break;
751 }
752 }
753
754 if (exprNode_isDefined (e)) {
755 return e->val;
756 } else {
757 return multiVal_undefined;
758 }
759}
760
761/*@only@*/ exprNode
28bf4b0b 762exprNode_combineLiterals (exprNode e, exprNode rest)
763{
764 cstring ns;
765
766 /* Both must be string literals. */
767
768 if (exprNode_isUndefined (rest) || exprNode_isUndefined (e))
769 {
770 exprNode_free (rest);
771 return e;
772 }
773
774 if (!exprNode_isStringLiteral (e))
775 {
776 voptgenerror
777 (FLG_SYNTAX,
778 message ("Constant concatentation is ungrammatical: %s %s", exprNode_unparse (e),
779 exprNode_unparse (rest)),
780 e->loc);
781 exprNode_free (rest);
782 return e;
783 }
784
785 if (!exprNode_isStringLiteral (rest))
786 {
787 voptgenerror
788 (FLG_SYNTAX,
789 message ("Constant concatentation is ungrammatical: %s %s", exprNode_unparse (e), exprNode_unparse (rest)),
790 rest->loc);
791
792 exprNode_free (rest);
793 return e;
794 }
795
796 ns = cstring_concat (multiVal_forceString (exprNode_getValue (e)),
797 multiVal_forceString (exprNode_getValue (rest)));
798
799 multiVal_free (e->val);
800 exprData_free (e->edata, e->kind);
801 e->edata = exprData_makeLiteral (cstring_copy (ns));
802 e->val = multiVal_makeString (ns);
803 exprNode_free (rest);
804 return e;
805}
806
807/*@only@*/ exprNode
808exprNode_rawStringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
616915dd 809{
810 exprNode e = exprNode_createLoc (ctype_string, loc);
28bf4b0b 811 int len = cstring_length (t);
616915dd 812
813 if (context_getFlag (FLG_STRINGLITERALLEN))
814 {
815 if (len > context_getValue (FLG_STRINGLITERALLEN))
816 {
817 voptgenerror (FLG_STRINGLITERALLEN,
818 message
819 ("String literal length (%d) exceeds maximum "
28bf4b0b 820 "length (%d): \"%s\"",
616915dd 821 len,
822 context_getValue (FLG_STRINGLITERALLEN),
823 t),
824 e->loc);
825 }
826 }
827
616915dd 828 e->kind = XPR_STRINGLITERAL;
28bf4b0b 829 e->val = multiVal_makeString (cstring_copy (t));
616915dd 830 e->edata = exprData_makeLiteral (t);
12f2ffe9 831 e->sref = sRef_makeConst (ctype_string);
616915dd 832
833 if (context_getFlag (FLG_READONLYSTRINGS))
834 {
835 sRef_setAliasKind (e->sref, AK_STATIC, fileloc_undefined);
836 sRef_setExKind (e->sref, XO_OBSERVER, loc);
837 }
838 else
839 {
840 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
841 }
842
843 return (e); /* s released */
844}
845
28bf4b0b 846/*@only@*/ exprNode
847exprNode_stringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
848{
849 int len = cstring_length (t) - 2;
850 char *ts = cstring_toCharsSafe (t);
851 char *s = cstring_toCharsSafe (cstring_create (len + 1));
852
853 llassert (*ts == '\"' && *(ts + len + 1) == '\"');
854 strncpy (s, ts+1, size_fromInt (len));
855 *(s + len) = '\0';
856 cstring_free (t);
857 return exprNode_rawStringLiteral (cstring_fromCharsO (s), loc);
858}
859
616915dd 860exprNode exprNode_fromUIO (cstring c)
861{
862 fileloc loc = context_getSaveLocation ();
863 exprNode e = exprNode_createPlain (ctype_unknown);
864
865 e->kind = XPR_VAR;
866
867 if (fileloc_isUndefined (loc))
868 {
869 loc = fileloc_copy (g_currentloc);
870 }
871
872 e->loc = loc; /* save loc was mangled */
873 e->sref = defref;
874
875 if (usymtab_exists (c))
876 {
877 uentry ue = usymtab_lookupEither (c);
878
879 if (uentry_isDatatype (ue)
880 && uentry_isSpecified (ue))
881 {
882 llfatalerror
883 (message ("%q: Specified datatype %s used in code, but not defined. "
884 "(Cannot continue reasonably from this error.)",
885 fileloc_unparse (e->loc), c));
886 }
887 else
888 {
889 BADBRANCH;
890 }
891 }
892
893 llassertprint (!usymtab_exists (c), ("Entry exists: %s", c));
894
895 /*
896 ** was supercedeGlobalEntry...is this better?
897 */
898
899 if (!context_inIterEnd ())
900 {
901 if (context_inMacro ())
902 {
903 if (context_getFlag (FLG_UNRECOG))
904 {
905 voptgenerror
906 (FLG_MACROUNDEF,
907 message ("Unrecognized identifier in macro definition: %s", c), e->loc);
908 }
909 else
910 {
911 flagcode_recordSuppressed (FLG_UNRECOG);
912 }
913 }
914 else
915 {
916 voptgenerror
28bf4b0b 917 (FLG_UNRECOG, message ("Unrecognized identifier: %s", c), e->loc);
616915dd 918 }
919 }
920
921 e->edata = exprData_makeId (uentry_makeUnrecognized (c, fileloc_copy (loc)));
922
923 /* No alias errors for unrecognized identifiers */
924 sRef_setAliasKind (e->sref, AK_ERROR, loc);
925
926 return (e);
927}
928
929exprNode exprNode_createId (/*@observer@*/ uentry c)
930{
931 if (uentry_isValid (c))
932 {
933 exprNode e = exprNode_new ();
934
935 e->typ = uentry_getType (c);
936
937 if (uentry_isFunction (c)
938 && !sRef_isLocalVar (uentry_getSref (c)))
939 {
940 e->sref = sRef_undefined;
941 }
942 else
943 {
944 e->sref = uentry_getSref (c);
945 }
946
947 if (sRef_isStateUnknown (e->sref) && uentry_isNonLocal (c))
948 {
949 sRef_setDefined (e->sref, fileloc_undefined);
950 }
951
952 /*
953 ** yoikes! leaving this out was a heinous bug...that would have been
954 ** caught if i had lclint working first. gag!
955 */
956
957 e->etext = cstring_undefined;
958
959 if (uentry_isEitherConstant (c))
960 {
961 e->kind = XPR_CONST;
962 e->val = multiVal_copy (uentry_getConstantValue (c));
963 }
964 else
965 {
966 e->kind = XPR_VAR;
967 e->val = multiVal_unknown ();
968 }
969
970 e->edata = exprData_makeId (c);
971 e->loc = context_getSaveLocation ();
972
973 if (fileloc_isUndefined (e->loc))
974 {
975 fileloc_free (e->loc);
976 e->loc = fileloc_copy (g_currentloc);
977 }
978
979 e->guards = guardSet_new ();
980 e->sets = sRefSet_new ();
981 e->msets = sRefSet_new ();
982 e->uses = sRefSet_new ();
983
984 /*> missing fields, detected by lclint <*/
985 e->exitCode = XK_NEVERESCAPE;
986 e->isJumpPoint = FALSE;
987 e->canBreak = FALSE;
988 e->mustBreak = FALSE;
989
84c9ffbf 990 exprNode_defineConstraints(e);
991
616915dd 992 return e;
993 }
994 else
995 {
28bf4b0b 996 return exprNode_createUnknown ();
616915dd 997 }
998}
999
1000/*@notnull@*/ exprNode
1001exprNode_fromIdentifier (/*@observer@*/ uentry c)
1002{
1003 exprNode ret;
1004
1005 if (context_justPopped ()) /* watch out! c could be dead */
1006 {
1007 uentry ce = usymtab_lookupSafe (LastIdentifier ());
1008
1009 if (uentry_isValid (ce))
1010 {
1011 c = ce;
1012 }
1013 else
1014 {
1015 llbuglit ("Looks like Aunt Millie forgot to walk to dog again.");
1016 }
1017 }
1018
1019 ret = exprNode_fromIdentifierAux (c);
1020
1021 return ret;
1022}
1023
1024
1025static /*@only@*/ /*@notnull@*/ exprNode
1026exprNode_fromIdentifierAux (/*@observer@*/ uentry c)
1027{
1028 exprNode e = exprNode_createId (c);
1029 sRef sr = e->sref;
1030
1031 uentry_setUsed (c, e->loc);
1032
28bf4b0b 1033 if (uentry_isVar (c) && sRef_isFileOrGlobalScope (sr))
616915dd 1034 {
1035 checkGlobUse (c, FALSE, e);
1036 }
1037
1038 return (e);
1039}
1040
1041static bool
1042exprNode_isZero (exprNode e)
1043{
1044 if (exprNode_isDefined (e))
1045 {
1046 multiVal m = exprNode_getValue (e);
1047
1048 if (multiVal_isInt (m))
1049 {
1050 return (multiVal_forceInt (m) == 0);
1051 }
1052 }
1053
1054 return FALSE;
1055}
1056
1057static bool
1058exprNode_isNonNegative (exprNode e)
1059{
1060 if (exprNode_isDefined (e))
1061 {
1062 multiVal m = exprNode_getValue (e);
1063
1064 if (multiVal_isInt (m))
1065 {
1066 return (multiVal_forceInt (m) >= 0);
1067 }
1068 }
1069
1070 return FALSE;
1071}
1072
1073/*
1074** a[x] - uses a but NOT a[]
1075** result sref = a[] (set/use in assignment)
1076**
1077** The syntax x[a] is also legal in C, and has the same
1078** semantics. If ind is an array, and arr is an int, flip
1079** the arguments.
1080*/
1081
1082/*@only@*/ exprNode
1083exprNode_arrayFetch (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
1084{
1085 /*
1086 ** error in arr, error propagates (no new messages)
1087 ** error in ind, assume valid and continue
1088 */
1089
1090 if (exprNode_isError (e1))
1091 {
1092 exprNode_free (e2);
1093 return (exprNode_makeError ());
1094 }
1095 else
1096 {
1097 exprNode arr;
1098 exprNode ind;
1099 ctype carr = exprNode_getType (e1);
1100 ctype crarr = ctype_realType (carr);
1101
1102 /*
1103 ** this sets up funny aliasing, that leads to spurious
1104 ** lclint errors. Hence, the i2 comments.
1105 */
1106
1107 if (!ctype_isRealArray (crarr)
1108 && ctype_isRealNumeric (crarr)
1109 && !exprNode_isError (e2)
1110 && ctype_isRealAP (exprNode_getType (e2))) /* fetch like 3[a] */
1111 {
1112 arr = e2;
1113 ind = e1;
1114
1115 carr = exprNode_getType (arr);
1116 crarr = ctype_realType (carr);
1117 }
1118 else
1119 {
1120 arr = e1;
1121 ind = e2;
1122 }
1123
1124 if (sRef_possiblyNull (arr->sref))
1125 {
1126 if (!usymtab_isGuarded (arr->sref))
1127 {
1128 if (optgenerror (FLG_NULLDEREF,
1129 message ("Index of %s pointer %q: %s",
1130 sRef_nullMessage (arr->sref),
1131 sRef_unparse (arr->sref),
1132 exprNode_unparse (arr)),
1133 arr->loc))
1134 {
1135 sRef_showNullInfo (arr->sref);
1136
1137 /* suppress future messages */
1138 sRef_setNullError (arr->sref);
1139 }
1140 }
1141 }
1142
1143 if (exprNode_isError (ind))
1144 {
1145 if ((ctype_isArrayPtr (crarr)
1146 && !ctype_isFunction (crarr))
1147 || ctype_isUnknown (carr))
1148 {
1149 exprNode ret = exprNode_createPartialCopy (arr);
1150
1151 if (ctype_isKnown (carr))
1152 {
1153 ret->typ = ctype_baseArrayPtr (crarr);
1154 }
1155 else
1156 {
1157 ret->typ = ctype_unknown;
1158 }
1159
1160 ret->sref = sRef_makeArrayFetch (arr->sref);
1161
1162 ret->kind = XPR_FETCH;
1163
1164 /*
1165 ** Because of funny aliasing (when arr and ind are
1166 ** flipped) spurious errors would be reported here.
1167 */
1168
1169 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1170 checkSafeUse (ret, arr->sref);
1171 return (ret);
1172 }
1173 else
1174 {
1175 voptgenerror (FLG_TYPE,
1176 message ("Array fetch from non-array (%t): %s[%s]", carr,
1177 exprNode_unparse (e1), exprNode_unparse (e2)),
1178 arr->loc);
1179 exprNode_free (arr);
1180 return (exprNode_makeError ());
1181 }
1182 }
1183 else
1184 {
1185 if (!ctype_isForceRealInt (&(ind->typ)))
1186 {
1187 ctype rt = ctype_realType (ind->typ);
1188
1189 if (ctype_isChar (rt))
1190 {
1191 vnoptgenerror
1192 (FLG_CHARINDEX,
1193 message ("Array fetch using non-integer, %t: %s[%s]",
1194 ind->typ,
1195 exprNode_unparse (e1), exprNode_unparse (e2)),
1196 arr->loc);
1197 }
1198 else if (ctype_isEnum (rt))
1199 {
1200 vnoptgenerror
1201 (FLG_ENUMINDEX,
1202 message ("Array fetch using non-integer, %t: %s[%s]",
1203 ind->typ,
1204 exprNode_unparse (e1), exprNode_unparse (e2)),
1205 arr->loc);
1206 }
1207 else
1208 {
1209 voptgenerror
1210 (FLG_TYPE,
1211 message ("Array fetch using non-integer, %t: %s[%s]",
1212 ind->typ,
1213 exprNode_unparse (e1), exprNode_unparse (e2)),
1214 arr->loc);
1215 }
1216
1217 multiVal_free (ind->val);
1218 ind->val = multiVal_unknown ();
1219 }
1220
1221 if (ctype_isArrayPtr (crarr) && !ctype_isFunction (crarr))
1222 {
1223 exprNode ret = exprNode_createSemiCopy (arr);
1224 multiVal m = exprNode_getValue (ind);
1225
1226 ret->typ = ctype_baseArrayPtr (crarr);
1227 ret->kind = XPR_FETCH;
1228
1229 if (multiVal_isInt (m))
1230 {
1231 int i = (int) multiVal_forceInt (m);
1232
1233 if (sRef_isValid (arr->sref)) {
1234 ret->sref = sRef_makeArrayFetchKnown (arr->sref, i);
1235 } else {
1236 ret->sref = sRef_undefined;
1237 }
1238 }
1239 else
1240 {
28bf4b0b 1241 ret->sref = sRef_makeArrayFetch (arr->sref);
616915dd 1242 }
1243
1244 ret->sets = sRefSet_realNewUnion (arr->sets, ind->sets);
1245 ret->msets = sRefSet_realNewUnion (arr->msets, ind->msets);
1246 ret->uses = sRefSet_realNewUnion (arr->uses, ind->uses);
1247
1248 /* (see comment on spurious errors above) */
1249 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1250
1251 exprNode_checkUse (ret, ind->sref, ind->loc);
1252 exprNode_checkUse (ret, arr->sref, arr->loc);
1253
1254 return (ret);
1255 }
1256 else
1257 {
1258 if (ctype_isUnknown (carr))
1259 {
1260 exprNode ret = exprNode_createPartialCopy (arr);
1261
1262 ret->kind = XPR_FETCH;
1263 ret->typ = ctype_unknown;
1264 ret->sets = sRefSet_union (ret->sets, ind->sets);
1265 ret->msets = sRefSet_union (ret->msets, ind->msets);
1266 ret->uses = sRefSet_union (ret->uses, ind->uses);
1267
1268 /* (see comment on spurious errors above) */
1269 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1270
1271 exprNode_checkUse (ret, ind->sref, ind->loc);
1272 exprNode_checkUse (ret, arr->sref, arr->loc);
1273 return (ret);
1274 }
1275 else
1276 {
1277 voptgenerror
1278 (FLG_TYPE,
1279 message ("Array fetch from non-array (%t): %s[%s]", carr,
1280 exprNode_unparse (e1), exprNode_unparse (e2)),
1281 arr->loc);
1282
1283 exprNode_free (arr);
1284 exprNode_free (ind);
1285
1286 return (exprNode_makeError ());
1287 }
1288 }
1289 }
1290 }
1291 BADEXIT;
1292}
1293
1294
1295static int
1296checkArgs (uentry fcn, /*@dependent@*/ exprNode f, ctype t,
1297 exprNodeList args, exprNode ret)
1298{
1299 return (checkArgsReal (fcn, f, ctype_argsFunction (t), args, FALSE, ret));
1300}
1301
1302/*
1303** checkPrintfArgs --- checks arguments for printf-like functions
1304** Arguments before ... have already been checked.
1305** The argument before the ... is a char *.
1306** argno is the format string argument.
1307*/
1308
1309static void
1310checkPrintfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1311 exprNodeList args, exprNode ret, int argno)
1312{
1313 /*
1314 ** the last argument before the elips is the format string
1315 */
1316
1317 int i = argno;
1318 fileloc formatloc;
1319 int nargs = exprNodeList_size (args);
1320 uentryList params = uentry_getParams (fcn);
1321 exprNode a;
1322
1323 /*
1324 ** These should be ensured by checkSpecialFunction
1325 */
1326
1327 llassert (uentryList_size (params) == argno + 1);
1328 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1329
1330 a = exprNodeList_getN (args, argno - 1);
1331 formatloc = fileloc_copy (exprNode_loc (a));
1332
1333 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1334 && exprNode_knownStringValue (a))
1335 {
1336 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1337 char *code = format;
1338 char *ocode = code;
1339
1340 nargs = exprNodeList_size (args);
1341
1342 while ((code = strchr (code, '%')) != NULL)
1343 {
1344 char *origcode = code;
28bf4b0b 1345 cstring codetext = cstring_newEmpty ();
616915dd 1346 char key = *(++code);
1347 ctype modtype = ctype_int;
1348 bool modified = FALSE;
1349
1350 fileloc_addColumn (formatloc, code - ocode);
1351
28bf4b0b 1352 codetext = cstring_appendChar (codetext, key);
1353
616915dd 1354 /* ignore flags */
1355 while (isFlagKey (key))
1356 {
1357 key = *(++code);
28bf4b0b 1358 codetext = cstring_appendChar (codetext, key);
616915dd 1359 fileloc_incColumn (formatloc);
1360 }
1361
1362 if (key == 'm') /* skipped in syslog */
1363 {
1364 continue;
1365 }
1366
1367 /* ignore field width */
1368 while (isdigit ((int) key) != 0)
1369 {
1370 key = *(++code);
28bf4b0b 1371 codetext = cstring_appendChar (codetext, key);
616915dd 1372 fileloc_incColumn (formatloc);
1373 }
1374
1375 /* ignore precision */
1376 if (key == '.')
1377 {
1378 key = *(++code);
28bf4b0b 1379 codetext = cstring_appendChar (codetext, key);
616915dd 1380 fileloc_incColumn (formatloc);
1381
1382 /*
1383 ** In printf, '*' means: read the next arg as an int for the
1384 ** field width. This seems to be missing from my copy of the
1385 ** standard x3.159-1989. Setion 4.9.6.1 refers to * (described
1386 ** later) but never does.
1387 */
1388
1389 if (key == '*')
1390 {
1391 ; /* don't do anything --- handle later */
1392 }
1393 else
1394 {
1395 while (isdigit ((int) key) != 0)
1396 {
1397 key = *(++code);
28bf4b0b 1398 codetext = cstring_appendChar (codetext, key);
616915dd 1399 fileloc_incColumn (formatloc);
1400 }
1401 }
1402 }
1403
1404 if (key == 'h')
1405 {
1406 modtype = ctype_sint; /* short */
1407 key = *(++code);
28bf4b0b 1408 codetext = cstring_appendChar (codetext, key);
616915dd 1409 fileloc_incColumn (formatloc);
1410 }
1411 else if (key == 'l' || key == 'L')
1412 {
1413 modtype = ctype_lint; /* long */
1414 key = *(++code);
28bf4b0b 1415 codetext = cstring_appendChar (codetext, key);
616915dd 1416 fileloc_incColumn (formatloc);
1417
1418 if (key == 'l' || key == 'L') {
1419 modtype = ctype_llint; /* long long */
1420 key = *(++code);
28bf4b0b 1421 codetext = cstring_appendChar (codetext, key);
616915dd 1422 fileloc_incColumn (formatloc);
1423 }
1424 }
1425 else
1426 {
1427 ; /* no modifier */
1428 }
1429
1430 /* now, key = type of conversion to apply */
1431 ++code;
1432 fileloc_incColumn (formatloc);
1433
1434 if (key != '%')
1435 {
1436 if (i >= nargs)
1437 {
1438 if (optgenerror
1439 (FLG_TYPE,
1440 message ("No argument corresponding to %q format "
28bf4b0b 1441 "code %d (%%%s): \"%s\"",
616915dd 1442 uentry_getName (fcn),
28bf4b0b 1443 i, codetext,
616915dd 1444 cstring_fromChars (format)),
1445 f->loc))
1446 {
1447 if (fileloc_isDefined (formatloc)
1448 && context_getFlag (FLG_SHOWCOL))
1449 {
1450 llgenindentmsg (cstring_makeLiteral ("Corresponding format code"),
1451 formatloc);
1452 }
1453 }
1454 i++;
1455 }
1456 else
1457 {
1458 a = exprNodeList_getN (args, i);
1459 i++;
1460
1461 if (!exprNode_isError (a))
1462 {
1463 ctype expecttype;
1464
1465 switch (key)
1466 {
1467 case '*': /* int argument for fieldwidth */
1468 expecttype = ctype_int;
1469 *(--code) = '%'; /* convert it for next code */
1470 fileloc_subColumn (formatloc, 1);
1471 /*@switchbreak@*/ break;
1472 case 'u':
1473 case 'o':
1474 expecttype = ctype_combine (ctype_uint, modtype);
1475 /*@switchbreak@*/ break;
1476
1477 case 'i': /* int argument */
1478 case 'd':
1479 expecttype = ctype_combine (ctype_int, modtype);
1480 /*@switchbreak@*/ break;
1481
28bf4b0b 1482 case 'x': /* unsigned int */
616915dd 1483 case 'X':
28bf4b0b 1484 expecttype = ctype_combine (ctype_uint, modtype);
1485
616915dd 1486 /*@switchbreak@*/ break;
1487
1488 case 'e':
1489 case 'E':
1490 case 'g':
1491 case 'G':
1492 case 'f': /* double */
1493 expecttype = ctype_combine (ctype_double, modtype);
1494 /*@switchbreak@*/ break;
1495
1496 case 'c': /* int converted to char (check its a char?) */
1497 expecttype = ctype_makeConj (ctype_char, ctype_uchar);
1498 /*@switchbreak@*/ break;
1499
1500 case 's': /* string */
1501 expecttype = ctype_string;
1502 /*@switchbreak@*/ break;
1503 case '[':
1504 /* skip to ']' */
1505 while (((key = *(++code)) != ']')
1506 && (key != '\0'))
1507 {
28bf4b0b 1508 codetext = cstring_appendChar (codetext, key);
616915dd 1509 fileloc_incColumn (formatloc);
1510 }
1511
1512 if (key == '\0')
1513 {
1514 llfatalerrorLoc
1515 (message ("Bad character set format: %s",
1516 cstring_fromChars (origcode)));
1517 }
1518
1519 expecttype = ctype_string;
1520 /*@switchbreak@*/ break;
1521
1522 case 'p': /* pointer */
1523 expecttype = ctype_makePointer (ctype_void);
346fab44 1524 uentry_setDefState (regArg, SS_RELDEF); /* need not be defined */
1525 sRef_setPosNull (uentry_getSref (regArg), fileloc_undefined); /* could be null */
616915dd 1526 /*@switchbreak@*/ break;
1527
1528 case 'n': /* pointer to int, modified by call! */
1529 expecttype = ctype_combine (ctype_makePointer (ctype_int), modtype);
1530 modified = TRUE;
1531 uentry_setDefState (regArg, SS_ALLOCATED); /* corresponds to out */
1532 /*@switchbreak@*/ break;
1533
1534 case 'm': /* in a syslog, it doesn't consume an argument */
1535 /* should check we're really doing syslog */
1536
1537 /*@switchbreak@*/ break;
1538
1539
1540 default:
1541 expecttype = ctype_unknown;
1542
1543 voptgenerror
1544 (FLG_FORMATCODE,
1545 message ("Unrecognized format code: %s",
1546 cstring_fromChars (origcode)),
1547 fileloc_isDefined (formatloc)
1548 ? formatloc : g_currentloc);
1549
1550 /*@switchbreak@*/ break;
1551 }
1552
1553 if (!(exprNode_matchArgType (expecttype, a)))
1554 {
1555 if (ctype_isVoidPointer (expecttype)
1556 && ctype_isRealAbstract (a->typ)
1557 && (context_getFlag (FLG_ABSTVOIDP)))
1558 {
1559 ;
1560 }
1561 else
1562 {
1563 if (llgenformattypeerror
1564 (expecttype, exprNode_undefined,
1565 a->typ, a,
28bf4b0b 1566 message ("Format argument %d to %q (%%%s) expects "
616915dd 1567 "%t gets %t: %s",
1568 i - argno,
1569 uentry_getName (fcn),
28bf4b0b 1570 codetext,
1571 expecttype,
616915dd 1572 a->typ, exprNode_unparse (a)),
1573 a->loc))
1574 {
1575 if (fileloc_isDefined (formatloc)
1576 && context_getFlag (FLG_SHOWCOL))
1577 {
1578 llgenindentmsg
1579 (cstring_makeLiteral
1580 ("Corresponding format code"),
1581 formatloc);
1582 }
1583 }
1584 }
1585 }
1586
1587 uentry_setType (regArg, expecttype);
1588 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
1589
1590 if (ctype_equal (expecttype, ctype_string))
1591 {
1592 exprNode_checkUse (a, sRef_makePointer (a->sref), a->loc);
1593 }
1594
1595 uentry_setType (regArg, ctype_unknown);
1596 uentry_fixupSref (regArg);
346fab44 1597
616915dd 1598 if (modified)
1599 {
1600 exprNode_checkCallModifyVal (a->sref, args, f, ret);
1601 }
1602 }
1603 else
1604 {
1605 ;
1606 }
1607 }
1608 }
28bf4b0b 1609
616915dd 1610 ocode = code;
28bf4b0b 1611 cstring_free (codetext);
616915dd 1612 }
1613
1614 if (i < nargs)
1615 {
1616 voptgenerror (FLG_TYPE,
28bf4b0b 1617 message ("Format string for %q has %d arg%&, given %d",
616915dd 1618 uentry_getName (fcn), i - argno, nargs - argno),
1619 f->loc);
1620 }
1621 }
1622 else
1623 {
1624 /* no checking possible for compile-time unknown format strings */
28bf4b0b 1625 if (exprNode_isDefined (a))
1626 {
1627 voptgenerror
1628 (FLG_FORMATCONST,
1629 message ("Format string parameter to %s is not a compile-time constant: %s",
1630 exprNode_unparse (f),
1631 exprNode_unparse (a)),
1632 f->loc);
1633 }
616915dd 1634 }
28bf4b0b 1635
616915dd 1636 fileloc_free (formatloc);
1637}
1638
1639static void
1640checkScanfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1641 exprNodeList args, exprNode ret, int argno)
1642{
1643 int i = argno;
1644 fileloc formatloc;
1645 int nargs = exprNodeList_size (args);
1646 uentryList params = uentry_getParams (fcn);
1647 exprNode a;
1648
1649 /*
1650 ** These should be ensured by checkSpecialFunction
1651 */
1652
1653 llassert (uentryList_size (params) == argno + 1);
1654 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1655
1656 a = exprNodeList_getN (args, argno - 1);
1657 formatloc = fileloc_copy (exprNode_loc (a));
1658
1659 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1660 && exprNode_knownStringValue (a))
1661 {
1662 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1663 char *code = format;
1664 char *ocode = code;
1665
1666 nargs = exprNodeList_size (args);
1667
1668 while ((code = strchr (code, '%')) != NULL)
1669 {
1670 char *origcode = code;
1671 char key = *(++code);
28bf4b0b 1672 cstring codetext = cstring_newEmpty ();
616915dd 1673 ctype modtype = ctype_int;
1674 char modifier = '\0';
1675 bool modified = TRUE;
1676 bool ignore = FALSE;
1677
28bf4b0b 1678 codetext = cstring_appendChar (codetext, key);
616915dd 1679 fileloc_addColumn (formatloc, code - ocode);
1680
1681 /*
1682 ** this is based on ANSI standard library description of fscanf
1683 ** (from ANSI standard X3.159-1989, 4.9.6.1)
1684 */
1685
1686 /* '*' suppresses assignment (does not need match argument) */
1687
1688 if (key == '*')
1689 {
1690 key = *(++code);
28bf4b0b 1691 codetext = cstring_appendChar (codetext, key);
616915dd 1692 modified = FALSE;
1693 ignore = TRUE;
1694 fileloc_incColumn (formatloc);
1695 }
1696
1697 /* ignore field width */
1698 while (isdigit ((int) key) != 0)
1699 {
1700 key = *(++code);
28bf4b0b 1701 codetext = cstring_appendChar (codetext, key);
616915dd 1702 fileloc_incColumn (formatloc);
1703 }
1704
1705 if (key == 'h')
1706 {
1707 modtype = ctype_sint; /* short */
1708 key = *(++code);
28bf4b0b 1709 codetext = cstring_appendChar (codetext, key);
616915dd 1710 fileloc_incColumn (formatloc);
1711 }
1712 else if (key == 'l' || key == 'L')
1713 {
1714 modtype = ctype_lint; /* long */
1715 modifier = key;
1716
1717 key = *(++code);
28bf4b0b 1718 codetext = cstring_appendChar (codetext, key);
1719
616915dd 1720 fileloc_incColumn (formatloc);
1721
1722 if (key == 'l' || key == 'L') {
1723 modtype = ctype_llint; /* long long */
1724 key = *(++code);
28bf4b0b 1725 codetext = cstring_appendChar (codetext, key);
616915dd 1726 fileloc_incColumn (formatloc);
1727 }
1728 }
1729 else
1730 {
1731 ; /* no modifier */
1732 }
1733
1734 /* now, key = type of conversion to apply */
1735 ++code;
1736 fileloc_incColumn (formatloc);
1737
1738 if (key != '%')
1739 {
1740 if (ignore)
1741 {
1742 ;
1743 }
1744 else
1745 {
1746 if (i >= nargs)
1747 {
1748 if (optgenerror
1749 (FLG_TYPE,
1750 message ("No argument corresponding to %q format "
28bf4b0b 1751 "code %d (%%%s): \"%s\"",
616915dd 1752 uentry_getName (fcn),
28bf4b0b 1753 i, codetext,
616915dd 1754 cstring_fromChars (format)),
1755 f->loc))
1756 {
1757 if (fileloc_isDefined (formatloc)
1758 && context_getFlag (FLG_SHOWCOL))
1759 {
1760 llgenindentmsg
1761 (cstring_makeLiteral ("Corresponding format code"),
1762 formatloc);
1763 }
1764 }
1765 i++;
1766 }
1767 else
1768 {
1769 a = exprNodeList_getN (args, i);
1770 i++;
1771
1772 if (!exprNode_isError (a))
1773 {
1774 ctype expecttype;
1775
1776 switch (key)
1777 {
1778 case '*': /* int argument for fieldwidth */
1779 expecttype = ctype_makePointer (ctype_int);
1780 *(--code) = '%'; /* convert it for next code */
1781 fileloc_subColumn (formatloc, 1);
1782 /*@switchbreak@*/ break;
1783 case 'u':
1784 case 'o':
1785 expecttype = ctype_makePointer (ctype_combine (ctype_uint, modtype));
1786 /*@switchbreak@*/ break;
1787
1788 case 'i':
1789 case 'd':
1790 case 'x':
1791 case 'X': /* unsigned int */
1792 expecttype = ctype_makePointer (ctype_combine (ctype_int, modtype));
1793 /*@switchbreak@*/ break;
1794
1795 case 'e':
1796 case 'E':
1797 case 'g':
1798 case 'G':
1799 case 'f':
1800 /* printf is double, scanf is float! */
1801
1802 if (modifier == 'l')
1803 {
1804 expecttype = ctype_makePointer (ctype_double);
1805 }
1806 else if (modifier == 'L')
1807 {
1808 expecttype = ctype_makePointer (ctype_ldouble);
1809 }
1810 else
1811 {
1812 llassert (modifier == '\0');
1813 expecttype = ctype_makePointer (ctype_float);
1814 }
1815 /*@switchbreak@*/ break;
1816
1817 case 'c': /* int converted to char (check its a char?) */
1818 expecttype = ctype_makePointer (ctype_makeConj (ctype_char, ctype_uchar));
1819 /*@switchbreak@*/ break;
1820
1821 case 's': /* string */
1822 expecttype = ctype_string;
1823 /*@switchbreak@*/ break;
1824
1825 case '[':
1826 /* skip to ']' */
1827 while (((key = *(++code)) != ']')
1828 && (key != '\0'))
1829 {
28bf4b0b 1830 codetext = cstring_appendChar (codetext, key);
616915dd 1831 fileloc_incColumn (formatloc);
1832 }
1833
1834 if (key == '\0')
1835 {
1836 llfatalerrorLoc
1837 (message ("Bad character set format: %s",
1838 cstring_fromChars (origcode)));
1839 }
1840
1841 expecttype = ctype_string;
1842 /*@switchbreak@*/ break;
346fab44 1843
616915dd 1844
1845 case 'p': /* pointer */
346fab44 1846 voptgenerror
1847 (FLG_FORMATCODE,
1848 message ("Format code should not be used in scanf: %s",
1849 cstring_fromChars (origcode)),
1850 fileloc_isDefined (formatloc)
1851 ? formatloc : g_currentloc);
1852
616915dd 1853 expecttype = ctype_unknown;
616915dd 1854 /*@switchbreak@*/ break;
1855
1856 case 'n': /* pointer to int, modified by call! */
1857 expecttype = ctype_makePointer (ctype_int);
1858 /*@switchbreak@*/ break;
1859
1860 default:
1861 expecttype = ctype_unknown;
1862
1863 voptgenerror
1864 (FLG_FORMATCODE,
1865 message ("Unrecognized format code: %s",
1866 cstring_fromChars (origcode)),
1867 fileloc_isDefined (formatloc)
1868 ? formatloc : g_currentloc);
1869
1870 /*@switchbreak@*/ break;
1871 }
1872
1873 if (!(exprNode_matchArgType (expecttype, a)))
1874 {
1875 if (ctype_isVoidPointer (expecttype)
1876 && ctype_isRealAbstract (a->typ)
1877 && (context_getFlag (FLG_ABSTVOIDP)))
1878 {
1879 ;
1880 }
1881 else
1882 {
28bf4b0b 1883 if (llgenformattypeerror
1884 (expecttype, exprNode_undefined,
1885 a->typ, a,
1886 message ("Format argument %d to %q (%%%s) expects "
1887 "%t gets %t: %s",
1888 i - argno,
1889 uentry_getName (fcn),
1890 codetext, expecttype,
1891 a->typ, exprNode_unparse (a)),
1892 a->loc))
616915dd 1893 {
28bf4b0b 1894 if (fileloc_isDefined (formatloc)
1895 && context_getFlag (FLG_SHOWCOL))
616915dd 1896 {
28bf4b0b 1897 llgenindentmsg
1898 (cstring_makeLiteral
1899 ("Corresponding format code"),
1900 formatloc);
616915dd 1901 }
1902 }
1903 }
1904 }
1905
1906 uentry_setType (outArg, expecttype);
1907 checkOneArg (outArg, a, f, FALSE, i+1, nargs);
1908 uentry_setType (outArg, ctype_unknown);
1909 uentry_fixupSref (outArg);
1910
1911 if (modified)
1912 {
1913 exprNode_checkCallModifyVal (a->sref, args, f, ret);
1914 }
1915 }
1916 else
1917 {
1918 /* a->sref = defref; */
1919 }
1920 }
1921 }
1922 }
28bf4b0b 1923
616915dd 1924 ocode = code;
28bf4b0b 1925 cstring_free (codetext);
616915dd 1926 }
1927
1928 if (i < nargs)
1929 {
1930 voptgenerror (FLG_TYPE,
28bf4b0b 1931 message ("Format string for %q has %d arg%&, given %d",
616915dd 1932 uentry_getName (fcn), i - argno, nargs - argno),
1933 f->loc);
1934 }
1935 }
1936 else
1937 {
1938 /* no checking possible for compile-time unknown format strings */
1939 }
1940
1941 fileloc_free (formatloc);
1942}
1943
1944static void
1945checkMessageArgs (/*@notnull@*/ /*@dependent@*/ exprNode f,
1946 uentry fcn,
1947 exprNodeList args,
1948 /*@unused@*/ int argno)
1949{
1950 /*
1951 ** the last argument before the elips is the format string
1952 */
1953
1954 int nargs = exprNodeList_size (args);
1955 int i = argno;
1956 fileloc formatloc;
1957 exprNode a;
1958
1959 a = exprNodeList_getN (args, argno - 1);
1960 formatloc = fileloc_copy (exprNode_loc (a));
1961
1962 if (ctype_isUnknown (cstringType)) {
1963 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
1964 {
1965 cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
1966 }
1967 }
1968
1969 if (ctype_isUnknown (ctypeType)) {
1970 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
1971 {
1972 ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
1973 }
1974 }
1975
1976 if (ctype_isUnknown (filelocType)) {
1977 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
1978 {
1979 filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
1980 }
1981 }
1982
1983 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1984 && exprNode_knownStringValue (a))
1985 {
1986 cstring format = multiVal_forceString (exprNode_getValue (a));
1987 char *code = cstring_toCharsSafe (format);
1988 char *ocode = code;
1989
1990 nargs = exprNodeList_size (args);
1991
1992 while ((code = strchr (code, '%')) != NULL)
1993 {
1994 char *origcode = code;
1995 char key = *(++code);
28bf4b0b 1996 cstring codetext = cstring_newEmpty ();
616915dd 1997 bool isOnly = FALSE;
1998
28bf4b0b 1999 codetext = cstring_appendChar (codetext, key);
2000
616915dd 2001 fileloc_addColumn (formatloc, code - ocode);
2002
2003 while (key >= '0' && key <= '9')
2004 {
2005 key = *(++code);
28bf4b0b 2006 codetext = cstring_appendChar (codetext, key);
616915dd 2007 fileloc_incColumn (formatloc);
2008 }
2009
2010 ++code;
2011 fileloc_incColumn (formatloc);
2012
2013 if (key != '%')
2014 {
28bf4b0b 2015 if (key == '&') /* plural marker */
616915dd 2016 {
2017 goto nextKey;
2018 }
2019
2020 if (i >= nargs)
2021 {
2022 voptgenerror
2023 (FLG_TYPE,
28bf4b0b 2024 message ("Message missing format arg %d (%%%s): \"%s\"",
2025 i + 1, codetext, format),
616915dd 2026 f->loc);
2027 i++;
2028 }
2029 else
2030 {
2031 a = exprNodeList_getN (args, i);
2032 i++;
2033
2034 nextKey:
2035 if (!exprNode_isError (a))
2036 {
2037 ctype expecttype;
2038
2039 /*@-loopswitchbreak@*/
2040
2041 switch (key)
2042 {
2043 case 'c':
2044 case 'h':
2045 expecttype = ctype_char; break;
2046 case 's':
2047 expecttype = cstringType; break;
2048 case 'q':
2049 expecttype = cstringType; isOnly = TRUE; break;
2050 case 'x':
2051 expecttype = cstringType; isOnly = TRUE; break;
2052 case 'd': expecttype = ctype_int; break;
2053 case 'u': expecttype = ctype_uint; break;
2054 case 'w': expecttype = ctype_ulint; break;
2055 case 'f': expecttype = ctype_float; break;
2056 case 'b': expecttype = ctype_bool; break;
2057 case 't': expecttype = ctypeType; break;
2058 case 'l': expecttype = filelocType; break;
28bf4b0b 2059 case '&': /* a wee bit of a hack methinks */
616915dd 2060 expecttype = ctype_int;
2061 break;
2062 case 'r': expecttype = ctype_bool; break;
2063 default:
2064 expecttype = ctype_unknown;
2065 voptgenerror
2066 (FLG_FORMATCODE,
2067 message ("Unrecognized format code: %s",
2068 cstring_fromChars (origcode)),
2069 fileloc_isDefined (formatloc)
2070 ? formatloc : g_currentloc);
2071 break;
2072 }
2073 /*@=loopswitchbreak@*/
2074
2075 if (!(exprNode_matchArgType (expecttype, a)))
2076 {
2077 if (ctype_isVoidPointer (expecttype)
2078 && ctype_isRealAbstract (a->typ)
2079 && (context_getFlag (FLG_ABSTVOIDP)))
2080 {
2081 ;
2082 }
2083 else
2084 {
2085 if (llgenformattypeerror
2086 (expecttype, exprNode_undefined,
2087 a->typ, a,
28bf4b0b 2088 message ("Format argument %d to %q (%%%s) expects "
616915dd 2089 "%t gets %t: %s",
2090 i - argno,
2091 uentry_getName (fcn),
28bf4b0b 2092 codetext, expecttype,
616915dd 2093 a->typ, exprNode_unparse (a)),
2094 a->loc))
2095 {
2096 if (fileloc_isDefined (formatloc)
2097 && context_getFlag (FLG_SHOWCOL))
2098 {
2099 llgenindentmsg
2100 (cstring_makeLiteral
2101 ("Corresponding format code"),
2102 formatloc);
2103 }
2104 }
2105 }
2106 }
2107
2108 if (ctype_equal (expecttype, cstringType))
2109 {
2110 if (isOnly)
2111 {
2112 checkOneArg (csOnlyArg, a, f, FALSE, i+1, nargs);
2113 uentry_fixupSref (csOnlyArg);
2114 }
2115 else
2116 {
2117 checkOneArg (csArg, a, f, FALSE, i+1, nargs);
2118 uentry_fixupSref (csArg);
2119 }
2120 }
2121 else
2122 {
2123 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
2124 uentry_fixupSref (regArg);
2125 }
2126 }
2127 }
2128 }
28bf4b0b 2129
2130 cstring_free (codetext);
616915dd 2131 }
2132
2133 if (i < nargs)
2134 {
2135 voptgenerror (FLG_TYPE,
28bf4b0b 2136 message ("Format string for %q has %d arg%&, given %d",
616915dd 2137 uentry_getName (fcn), i - argno, nargs -argno),
2138 f->loc);
2139 }
2140 }
2141 else
2142 {
2143 /* no checking possible for compile-time unknown format strings */
2144 }
2145
2146 fileloc_free (formatloc);
2147}
2148
2149static void
2150 checkExpressionDefinedAux (/*@notnull@*/ exprNode e1,
2151 /*@notnull@*/ exprNode e2,
2152 sRefSet sets1,
2153 sRefSet sets2,
2154 lltok op,
2155 flagcode flag)
2156{
2157 bool hadUncon = FALSE;
2158
28bf4b0b 2159 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e1->sref)) &&
616915dd 2160 sRefSet_hasUnconstrained (sets2))
2161 {
2162 voptgenerror
2163 (FLG_EVALORDERUNCON,
2164 message
2165 ("Expression may have undefined behavior (%q used in right operand "
2166 "may set global variable %q used in left operand): %s %s %s",
2167 sRefSet_unparseUnconstrained (sets2),
2168 sRef_unparse (sRef_getRootBase (e1->sref)),
2169 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2170 e2->loc);
2171 }
2172
28bf4b0b 2173 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e2->sref)) &&
616915dd 2174 sRefSet_hasUnconstrained (sets1))
2175 {
2176 voptgenerror
2177 (FLG_EVALORDERUNCON,
2178 message
2179 ("Expression has undefined behavior (%q used in left operand "
2180 "may set global variable %q used in right operand): %s %s %s",
2181 sRefSet_unparseUnconstrained (sets1),
2182 sRef_unparse (e2->sref),
2183 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2184 e2->loc);
2185 }
2186
2187 sRefSet_realElements (e1->uses, sr)
2188 {
2189 if (sRef_isMeaningful (sr) && sRefSet_member (sets2, sr))
2190 {
2191 voptgenerror
2192 (FLG_EVALORDER,
2193 message
2194 ("Expression has undefined behavior (left operand uses %q, "
2195 "modified by right operand): %s %s %s",
2196 sRef_unparse (sr),
2197 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2198 e2->loc);
2199 }
2200 } end_sRefSet_realElements;
2201
2202 sRefSet_realElements (sets1, sr)
2203 {
2204 if (sRef_isMeaningful (sr))
2205 {
2206 if (sRef_same (sr, e2->sref))
2207 {
2208 voptgenerror
2209 (flag,
2210 message
2211 ("Expression has undefined behavior (value of right operand "
2212 "modified by left operand): %s %s %s",
2213 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2214 e2->loc);
2215 }
2216 else if (sRefSet_member (e2->uses, sr))
2217 {
2218 voptgenerror
2219 (flag,
2220 message
2221 ("Expression has undefined behavior (left operand modifies %q, "
2222 "used by right operand): %s %s %s",
2223 sRef_unparse (sr),
2224 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2225 e2->loc);
2226 }
2227 else
2228 {
2229 if (sRefSet_member (sets2, sr))
2230 {
2231 if (sRef_isUnconstrained (sr))
2232 {
2233 if (hadUncon)
2234 {
2235 ;
2236 }
2237 else
2238 {
2239 hadUncon = optgenerror
2240 (FLG_EVALORDERUNCON,
2241 message
2242 ("Expression may have undefined behavior. Left operand "
2243 "calls %q; right operand calls %q. The unconstrained "
2244 "functions may modify global state used by "
2245 "the other operand): %s %s %s",
2246 sRefSet_unparseUnconstrained (sets1),
2247 sRefSet_unparseUnconstrained (sets2),
2248 exprNode_unparse (e1), lltok_unparse (op),
2249 exprNode_unparse (e2)),
2250 e2->loc);
2251 }
2252 }
2253 else
2254 {
2255 voptgenerror
2256 (flag,
2257 message
2258 ("Expression has undefined behavior (both "
2259 "operands modify %q): %s %s %s",
2260 sRef_unparse (sr),
2261 exprNode_unparse (e1),
2262 lltok_unparse (op), exprNode_unparse (e2)),
2263 e2->loc);
2264 }
2265 }
2266 }
2267 }
2268 } end_sRefSet_realElements;
2269}
2270
2271static void checkExpressionDefined (exprNode e1, exprNode e2, lltok op)
2272{
2273 bool hasError = FALSE;
2274
2275 if (exprNode_isError (e1) || exprNode_isError (e2))
2276 {
2277 return;
2278 }
2279
2280 if (sRefSet_member (e2->sets, e1->sref))
2281 {
2282 if (e2->kind == XPR_CALL)
2283 {
2284 ;
2285 }
2286 else
2287 {
2288 hasError = optgenerror
2289 (FLG_EVALORDER,
2290 message ("Expression has undefined behavior "
ccf0a4a8 2291 "(value of left operand %s is modified "
2292 "by right operand %s): %s %s %s",
2293 exprNode_unparse (e1),
2294 exprNode_unparse (e2),
616915dd 2295 exprNode_unparse (e1), lltok_unparse (op),
2296 exprNode_unparse (e2)),
2297 e2->loc);
2298 }
2299 }
2300
2301 if (context_getFlag (FLG_EVALORDERUNCON))
2302 {
2303 if (sRefSet_member (e2->msets, e1->sref))
2304 {
2305 if (e2->kind == XPR_CALL)
2306 {
2307 ;
2308 }
2309 else
2310 {
2311 hasError = optgenerror
2312 (FLG_EVALORDER,
2313 message
2314 ("Expression has undefined behavior (value of left "
2315 "operand may be modified by right operand): %s %s %s",
2316 exprNode_unparse (e1), lltok_unparse (op),
2317 exprNode_unparse (e2)),
2318 e2->loc);
2319 }
2320 }
2321 }
2322
2323 if (!hasError)
2324 {
2325 checkExpressionDefinedAux (e1, e2, e1->sets, e2->sets, op, FLG_EVALORDER);
2326
2327 if (context_maybeSet (FLG_EVALORDERUNCON))
2328 {
2329 checkExpressionDefinedAux (e1, e2, e1->msets,
2330 e2->msets, op, FLG_EVALORDERUNCON);
2331 }
2332 }
2333}
2334
2335static void checkSequencing (exprNode p_f, exprNodeList p_args);
2336
2337static int
2338 checkArgsReal (uentry fcn, /*@dependent@*/ exprNode f, uentryList cl,
2339 exprNodeList args, bool isIter, exprNode ret)
2340{
2341 int special = 0;
2342
2343 if (!exprNode_isError (f))
2344 {
2345 if (!uentryList_isMissingParams (cl))
2346 {
2347 int nargs = exprNodeList_size (args);
2348 int expectargs = uentryList_size (cl);
2349 ctype last;
2350 int i = 0;
2351
2352 if (expectargs == 0)
2353 {
2354 if (nargs != 0)
2355 {
2356 if (isIter)
2357 {
2358 voptgenerror
2359 (FLG_TYPE,
2360 message ("Iter %q invoked with %d args, "
2361 "declared void",
2362 uentry_getName (fcn),
2363 nargs),
2364 f->loc);
2365 }
2366 else
2367 {
2368 voptgenerror
2369 (FLG_TYPE,
2370 message ("Function %s called with %d args, "
2371 "declared void",
2372 exprNode_unparse (f), nargs),
2373 f->loc);
2374 }
2375 }
2376 return special;
2377 }
2378
2379 last = uentry_getType (uentryList_getN (cl, expectargs - 1));
2380
2381 exprNodeList_reset (args);
2382
2383 uentryList_elements (cl, current)
2384 {
2385 ctype ct = uentry_getType (current);
2386 exprNode a;
2387
2388 if (ctype_isElips (ct))
2389 {
2390 /*
2391 ** do special checking for printf/scanf library functions
2392 **
2393 ** this is kludgey code, just for handling the special case
2394 **
2395 */
2396
2397 if (uentry_isPrintfLike (fcn))
2398 {
2399 checkPrintfArgs (f, fcn, args, ret, i);
2400 special = i;
2401 }
2402 else if (uentry_isScanfLike (fcn))
2403 {
2404 checkScanfArgs (f, fcn, args, ret, i);
2405 special = i;
2406 }
2407 else if (uentry_isMessageLike (fcn))
2408 {
2409 checkMessageArgs (f, fcn, args, i);
2410 special = i;
2411 }
2412 else
2413 {
2414 llassert (!uentry_isSpecialFunction (fcn));
2415 }
2416
2417 nargs = expectargs; /* avoid errors */
2418 break;
2419 }
2420 else
2421 {
2422 if (i >= nargs) break;
2423
2424 a = exprNodeList_current (args);
2425 exprNodeList_advance (args);
2426
2427 i++;
2428
2429 if (exprNode_isError (a))
2430 {
2431 ;
2432 }
2433 else
2434 {
2435 /*
2436 probably necessary? I'm not sure about this one
2437 checkMacroParen (a);
2438 */
2439
2440 f->guards = guardSet_union (f->guards, a->guards);
2441
2442 DPRINTF (("match arg: %s / %s", ctype_unparse (ct), ctype_unparse (a->typ)));
2443
2444 if (!(exprNode_matchArgType (ct, a)))
2445 {
2446 DPRINTF (("Args mismatch!"));
2447
2448 if (ctype_isVoidPointer (ct)
2449 && (ctype_isPointer (a->typ)
2450 && (ctype_isRealAbstract (ctype_baseArrayPtr (a->typ)))))
2451 {
2452 vnoptgenerror
2453 (FLG_ABSTVOIDP,
2454 message
2455 ("Pointer to abstract type (%t) used "
2456 "as void pointer "
2457 "(arg %d to %q): %s",
2458 a->typ, i,
2459 uentry_getName (fcn),
2460 exprNode_unparse (a)),
2461 a->loc);
2462 }
2463 else
2464 {
2465 if (isIter)
2466 {
2467 (void) gentypeerror
2468 (ct, exprNode_undefined,
2469 a->typ, a,
2470 message
2471 ("Iter %q expects arg %d to "
2472 "be %t gets %t: %s",
2473 uentry_getName (fcn),
2474 i, ct, a->typ, exprNode_unparse (a)),
2475 a->loc);
2476 }
2477 else
2478 {
2479 if (gentypeerror
2480 (ct,
2481 exprNode_undefined,
2482 a->typ,
2483 a,
2484 message
2485 ("Function %q expects arg %d to be %t gets %t: %s",
2486 uentry_getName (fcn),
2487 i, ct, a->typ, exprNode_unparse (a)),
2488 a->loc))
2489 {
2490 DPRINTF (("Types: %s / %s",
2491 ctype_unparse (ct),
2492 ctype_unparse (a->typ)));
2493 }
2494
2495 /*
2496 ** Clear null marker for abstract types.
2497 ** (It is not revealed, so suppress future messages.)
2498 */
2499
2500 if (ctype_isAbstract (a->typ))
2501 {
2502 sRef_setNullUnknown (exprNode_getSref (a), a->loc);
2503 }
2504 }
2505 }
2506 }
2507 }
2508 }
2509 } end_uentryList_elements ;
2510
2511
2512 if (expectargs != nargs) /* note: not != since we may have ... */
2513 {
2514 if (ctype_isElips (last))
2515 {
2516 voptgenerror
2517 (FLG_TYPE,
2518 message ("Function %s called with %d args, expects at least %d",
2519 exprNode_unparse (f),
2520 nargs, expectargs - 1),
2521 f->loc);
2522 }
2523 else
2524 {
2525 if (isIter)
2526 {
2527 voptgenerror
2528 (FLG_TYPE,
2529 message ("Iter %q invoked with %d args, expects %d",
2530 uentry_getName (fcn), nargs, expectargs),
2531 f->loc);
2532 }
2533 else
2534 {
2535 voptgenerror
2536 (FLG_TYPE,
2537 message ("Function %s called with %d args, expects %d",
2538 exprNode_unparse (f),
2539 nargs, expectargs),
2540 f->loc);
2541 }
2542 }
2543 }
2544 }
2545 }
2546
2547 return special;
2548}
2549
2550/*
2551** Check for undefined code sequences in function arguments:
2552**
2553** one parameter sets something used by another parameter
2554** one parameter sets something set by another parameter
2555*/
2556
2557static void
2558checkSequencingOne (exprNode f, exprNodeList args,
2559 /*@notnull@*/ exprNode el, int argno)
2560{
2561 /*
2562 ** Do second loop, iff +undefunspec
2563 */
2564
2565 int checkloop;
2566 int numloops = context_maybeSet (FLG_EVALORDERUNCON) ? 2 : 1;
2567
2568 for (checkloop = 0; checkloop < numloops; checkloop++)
2569 {
2570 sRefSet thissets;
2571
2572 if (checkloop == 0)
2573 {
2574 thissets = el->sets;
2575 }
2576 else
2577 {
2578 llassert (checkloop == 1);
2579 thissets = el->msets;
2580 }
2581
2582 sRefSet_realElements (thissets, thisset)
2583 {
2584 int j;
2585
2586 /*@access exprNodeList@*/
2587 for (j = 0; j < args->nelements; j++)
2588 {
2589 exprNode jl = args->elements[j];
2590 int thisargno = j + 1;
2591
2592 if (thisargno != argno && exprNode_isDefined (jl))
2593 {
2594 sRefSet otheruses = jl->uses;
2595
28bf4b0b 2596 if (sRef_isFileOrGlobalScope (sRef_getRootBase (jl->sref)) &&
616915dd 2597 sRefSet_hasUnconstrained (thissets))
2598 {
2599 voptgenerror
2600 (FLG_EVALORDERUNCON,
2601 /*@-sefparams@*/
2602 message
2603 ("%q used in argument %d may set "
2604 "global variable %q used by argument %d: %s(%q)",
2605 cstring_capitalizeFree (sRefSet_unparseUnconstrained (thissets)),
2606 /*@=sefparams@*/
2607 argno,
2608 sRef_unparse (sRef_getRootBase (jl->sref)),
2609 thisargno,
2610 exprNode_unparse (f), exprNodeList_unparse (args)),
2611 el->loc);
2612 }
2613
2614 if (sRefSet_member (otheruses, thisset))
2615 {
2616 if (sRef_isUnconstrained (thisset))
2617 {
2618 voptgenerror
2619 (FLG_EVALORDERUNCON,
2620 message
2621 ("Unconstrained functions used in arguments %d (%q) "
2622 "and %d (%s) may modify "
2623 "or use global state in undefined way: %s(%q)",
2624 argno,
2625 sRefSet_unparseUnconstrainedPlain (otheruses),
2626 thisargno,
2627 sRef_unconstrainedName (thisset),
2628 exprNode_unparse (f),
2629 exprNodeList_unparse (args)),
2630 el->loc);
2631 }
2632 else
2633 {
2634 voptgenerror
2635 (FLG_EVALORDER,
2636 message
2637 ("Argument %d modifies %q, used by argument %d "
2638 "(order of evaluation of actual parameters is "
2639 "undefined): %s(%q)",
2640 argno, sRef_unparse (thisset), thisargno,
2641 exprNode_unparse (f), exprNodeList_unparse (args)),
2642 el->loc);
2643 }
2644 }
2645 else
2646 {
2647 sRefSet othersets = jl->sets;
2648
2649 if (sRefSet_member (othersets, thisset))
2650 {
2651 if (sRef_isUnconstrained (thisset))
2652 {
2653 voptgenerror
2654 (FLG_EVALORDERUNCON,
2655 message
2656 ("Unconstrained functions used in "
2657 "arguments %d (%q) and %d (%s) may modify "
2658 "or use global state in undefined way: %s(%q)",
2659 argno,
2660 sRefSet_unparseUnconstrainedPlain (othersets),
2661 thisargno,
2662 sRef_unconstrainedName (thisset),
2663 exprNode_unparse (f), exprNodeList_unparse (args)),
2664 el->loc);
2665 }
2666 else
2667 {
2668 voptgenerror
2669 (FLG_EVALORDER,
2670 message
2671 ("Argument %d modifies %q, set by argument %d (order of"
2672 " evaluation of actual parameters is undefined): %s(%q)",
2673 argno, sRef_unparse (thisset), thisargno,
2674 exprNode_unparse (f), exprNodeList_unparse (args)),
2675 el->loc);
2676 }
2677 }
2678 }
2679 }
2680 }
2681 /*@noaccess exprNodeList@*/
2682 } end_sRefSet_realElements;
2683 }
2684}
2685
2686static void
2687checkSequencing (exprNode f, exprNodeList args)
2688{
2689 if (exprNodeList_size (args) > 1)
2690 {
2691 int i;
2692 exprNode el;
2693
2694 /*@access exprNodeList*/
2695
2696 for (i = 0; i < args->nelements; i++)
2697 {
2698 el = args->elements[i];
2699
2700 if (!exprNode_isError (el))
2701 {
2702 checkSequencingOne (f, args, el, i + 1);
2703 }
2704 }
2705 /*@noaccess exprNodeList*/
2706 }
2707}
2708
2709/*
2710** requires le = exprNode_getUentry (f)
2711*/
2712
2713static void
2714checkGlobMods (/*@notnull@*/ /*@dependent@*/ exprNode f,
2715 uentry le, exprNodeList args,
2716 /*@notnull@*/ exprNode ret, int specialArgs)
2717{
2718 bool isSpec = FALSE;
2719 bool hasMods = FALSE;
2720 cstring fname;
2721 globSet usesGlobs = globSet_undefined;
2722 sRefSet mods = sRefSet_undefined;
2723 bool freshMods = FALSE;
2724 uentryList params = uentryList_undefined;
2725
28bf4b0b 2726 DPRINTF (("Check glob mods: %s", exprNode_unparse (ret)));
2727
616915dd 2728 /*
2729 ** check globals and modifies
2730 */
2731
2732 setCodePoint ();
2733
2734 if (!uentry_isValid (le))
2735 {
2736 ctype fr = ctype_realType (f->typ);
2737
2738 if (ctype_isFunction (fr))
2739 {
2740 params = ctype_argsFunction (fr);
2741 }
2742 else
2743 {
2744 params = uentryList_missingParams;
2745 }
2746
2747 if (!context_getFlag (FLG_MODNOMODS)
2748 && !context_getFlag (FLG_GLOBUNSPEC))
2749 {
28bf4b0b 2750 checkUnspecCall (f, params, args);
616915dd 2751 }
2752
2753 return;
2754 }
2755
2756 fname = uentry_rawName (le);
2757
2758 setCodePoint ();
2759
2760 if (uentry_isFunction (le))
2761 {
2762 params = uentry_getParams (le);
2763 mods = uentry_getMods (le);
2764 hasMods = uentry_hasMods (le);
2765 usesGlobs = uentry_getGlobs (le);
2766 isSpec = uentry_isSpecified (le);
2767 }
2768 else /* not a function */
2769 {
2770 ctype ct = ctype_realType (uentry_getType (le));
2771
2772 llassertprint (uentry_isVar (le) && ctype_isFunction (ct),
2773 ("checkModGlobs: uentry not a function: %s",
2774 uentry_unparse (le)));
2775
2776 params = ctype_argsFunction (ct);
28bf4b0b 2777 return; /*@32 ! remove this? */
616915dd 2778 }
2779
2780 /*
2781 ** check globals
2782 */
2783
2784 setCodePoint ();
616915dd 2785
2786 globSet_allElements (usesGlobs, el)
2787 {
2788 if (sRef_isValid (el))
2789 {
2790 if (sRef_isInternalState (el) || sRef_isSystemState (el))
2791 {
2792 context_usedGlobal (el);
2793 exprNode_checkUse (f, el, f->loc);
2794
2795 if (context_checkInternalUse ())
2796 {
2797 if (!context_globAccess (el))
2798 {
2799 if (sRef_isSystemState (el)
2800 && !context_getFlag (FLG_MODFILESYSTEM))
2801 {
2802 ;
2803 }
2804 else
2805 {
2806 voptgenerror
2807 (FLG_INTERNALGLOBS,
2808 message
2809 ("Called procedure %s may access %q, but "
2810 "globals list does not include globals %s",
2811 exprNode_unparse (f),
2812 sRef_unparse (el),
2813 cstring_makeLiteralTemp (sRef_isInternalState (el)
2814 ? "internalState"
2815 : "fileSystem")),
2816 f->loc);
2817 }
2818 }
2819 }
2820 }
2821 else if (sRef_isNothing (el) || sRef_isSpecState (el))
2822 {
2823 ;
2824 }
2825 else
2826 {
2827 uentry gle = sRef_getUentry (el);
2828 sRef sr = sRef_updateSref (el);
2829
2830 if (sRef_isUndefGlob (el))
2831 {
2832 sRef_setDefined (sr, f->loc);
2833 exprNode_checkSet (f, sr);
2834 }
2835 else
2836 {
2837 /*
2838 ** check definition
2839 */
2840
2841 if (sRef_isAllocated (el))
2842 {
2843 exprNode_checkSet (f, sr);
2844 }
2845 else
2846 {
2847 if (sRef_isStateUndefined (sr))
2848 {
2849 voptgenerror
2850 (FLG_GLOBSTATE,
2851 message
2852 ("%s %q used by function undefined before call: %s",
2853 sRef_getScopeName (sr),
2854 sRef_unparse (sr),
2855 exprNode_unparse (f)),
2856 f->loc);
2857 sRef_setDefined (sr, f->loc);
2858 }
2859 exprNode_checkUse (f, sr, f->loc);
2860 }
2861
2862 checkGlobUse (gle, TRUE, f);
2863 }
2864
2865 if (sRef_isKilledGlob (el))
2866 {
2867 sRef_kill (sr, f->loc);
2868 context_usedGlobal (sr);
2869 }
2870 }
2871 }
2872 } end_globSet_allElements;
2873
2874 /*
2875 ** check modifies
2876 */
2877
2878 if (context_hasMods () || context_getFlag (FLG_MODNOMODS))
2879 {
2880 sRefSet smods = sRefSet_undefined;
2881
2882 /*
2883 ** NEED to check for modifies anything
2884 */
2885
2886 /*
2887 ** check each sRef that called function modifies (ml), is
2888 ** modifiable by tl
2889 */
2890
2891 setCodePoint ();
2892
2893 sRefSet_allElements (mods, s) /* s is something which may be modified */
2894 {
28bf4b0b 2895 DPRINTF (("Check modify: %s", sRef_unparse (s)));
2896
616915dd 2897 if (sRef_isKindSpecial (s))
2898 {
2899 if (sRef_isSpecInternalState (s))
2900 {
2901 if (context_getFlag (FLG_MODINTERNALSTRICT))
2902 {
2903 exprNode_checkCallModifyVal (s, args, f, ret);
2904 }
2905 else
2906 {
2907 sRefSet mmods = context_modList ();
2908
2909 sRefSet_allElements (mmods, el)
2910 {
2911 if (sRef_isInternalState (el))
2912 {
2913 sRef_setModified (el);
2914 }
2915 } end_sRefSet_allElements ;
2916 }
2917 }
2918 else
2919 {
2920 exprNode_checkCallModifyVal (s, args, f, ret);
2921 }
2922 }
2923 else
2924 {
2925 sRef rb = sRef_getRootBase (s);
2926
28bf4b0b 2927 if (sRef_isFileOrGlobalScope (rb))
616915dd 2928 {
2929 context_usedGlobal (rb);
2930 }
2931
2932 if (sRef_isFileStatic (s)
2933 && !fileId_equal (fileloc_fileId (f->loc),
2934 fileloc_fileId (uentry_whereDefined (le))))
2935 {
2936 smods = sRefSet_insert (smods, s);
2937 }
2938 else
2939 {
2940 exprNode_checkCallModifyVal (s, args, f, ret);
2941 }
2942 }
2943 } end_sRefSet_allElements;
2944
2945 setCodePoint ();
2946
2947 /*
2948 ** Static elements in modifies set can have nasty consequences.
2949 ** (I think...have not been able to reproduce a possible bug.)
2950 */
2951
2952 if (!sRefSet_isDefined (smods))
2953 {
2954 mods = sRefSet_newCopy (mods);
2955 freshMods = TRUE;
2956
2957 sRefSet_allElements (smods, el)
2958 {
2959 bool res = sRefSet_delete (mods, el);
2960
2961 llassert (res);
2962 } end_sRefSet_allElements;
2963
2964 sRefSet_free (smods);
2965 /*@-branchstate@*/
2966 }
2967 /*@=branchstate@*/
2968 }
2969 else if (sRefSet_isDefined (mods))
2970 { /* just check observers */
2971 setCodePoint ();
2972
2973 sRefSet_allElements (mods, s) /* s is something which may be modified */
2974 {
2975 sRef rb = sRef_getRootBase (s);
2976
2977 setCodePoint ();
2978
2979 if (sRef_isParam (rb))
2980 {
2981 sRef b = sRef_fixBaseParam (s, args);
2982
2983 if (sRef_isObserver (b))
2984 {
2985 exprNode e = exprNodeList_nth (args, sRef_getParam (rb));
2986
2987 if (optgenerror
2988 (FLG_MODOBSERVER,
2989 message ("Function call may modify observer%q: %s",
2990 sRef_unparsePreOpt (b), exprNode_unparse (e)),
2991 exprNode_loc (e)))
2992 {
2993 sRef_showExpInfo (b);
2994 }
2995 }
2996 }
2997 } end_sRefSet_allElements;
2998 }
2999 else
3000 {
3001 if (!hasMods) /* no specified modifications */
3002 {
3003 if (context_getFlag (FLG_MODOBSERVERUNCON))
3004 {
3005 exprNodeList_elements (args, e)
3006 {
3007 if (exprNode_isDefined (e))
3008 {
3009 sRef s = exprNode_getSref (e);
3010
3011 if (sRef_isObserver (s)
3012 && ctype_isMutable (sRef_getType (s)))
3013 {
3014 if (optgenerror
3015 (FLG_MODOBSERVERUNCON,
3016 message
3017 ("Call to unconstrained function %s may modify observer%q: %s",
3018 exprNode_unparse (f),
3019 sRef_unparsePreOpt (s), exprNode_unparse (e)),
3020 exprNode_loc (e)))
3021 {
3022 sRef_showExpInfo (s);
3023 }
3024 }
3025 }
3026 } end_exprNodeList_elements;
3027 }
3028 }
3029 }
3030
3031 checkAnyCall (f, fname, params, args, hasMods, mods, isSpec, specialArgs);
3032
3033 ret->uses = sRefSet_union (ret->uses, f->uses);
3034 ret->sets = sRefSet_union (ret->sets, f->sets);
3035 ret->msets = sRefSet_union (ret->msets, f->msets);
3036
3037 if (freshMods)
3038 {
3039 /*
3040 ** Spurious errors reported, because lclint can't tell
3041 ** mods must be fresh if freshMods is true.
3042 */
3043
3044 /*@i@*/ sRefSet_free (mods);
3045 }
3046
3047 setCodePoint ();
3048}
3049
3050void checkGlobUse (uentry glob, bool isCall, /*@notnull@*/ exprNode e)
3051{
3052 if (uentry_isVar (glob))
3053 {
3054 if (context_inFunctionLike ())
3055 {
3056 sRef sr = uentry_getSref (glob);
3057
3058 context_usedGlobal (sr);
3059
3060 if (context_checkGlobUse (glob))
3061 {
3062 if (!context_globAccess (sr))
3063 {
3064 if (isCall)
3065 {
3066 voptgenerror
3067 (FLG_GLOBALS,
3068 message ("Called procedure %s may access %s %q",
3069 exprNode_unparse (e),
3070 sRef_unparseScope (sr),
3071 uentry_getName (glob)),
3072 e->loc);
3073 }
3074 else
3075 {
3076 voptgenerror
3077 (FLG_GLOBALS,
3078 message ("Undocumented use of %s %s",
3079 sRef_unparseScope (sr),
3080 exprNode_unparse (e)),
3081 e->loc);
3082 }
3083 }
3084 }
3085 }
3086 }
3087 else
3088 {
3089 llbug (message ("Global not variable: %q", uentry_unparse (glob)));
3090 }
3091}
3092
28bf4b0b 3093static void
ccf0a4a8 3094reflectEnsuresClause (exprNode ret, uentry le, exprNode f, exprNodeList args)
28bf4b0b 3095{
3096 DPRINTF (("Reflect ensures clause: %s(%s) / %s / %s",
3097 exprNode_unparse (f), exprNodeList_unparse (args),
3098 uentry_unparseFull (le),
3099 stateClauseList_unparse (uentry_getStateClauseList (le))));
3100
3101 if (uentry_isValid (le) && uentry_isFunction (le))
3102 {
3103 stateClauseList sclauses = uentry_getStateClauseList (le);
3104
3105 if (stateClauseList_isDefined (sclauses))
3106 {
3107 DPRINTF (("Reflect ensures: %s / %s / %s",
3108 uentry_unparse (le),
3109 exprNode_unparse (f), exprNodeList_unparse (args)));
3110
3111 stateClauseList_elements (sclauses, cl)
3112 {
3113 if (stateClause_hasEnsures (cl))
3114 {
3115 /* Same in usymtab.c:1904 */
3116 if (stateClause_setsMetaState (cl))
3117 {
3118 qual q = stateClause_getMetaQual (cl);
3119 annotationInfo ainfo = qual_getAnnotationInfo (q);
3120 metaStateInfo minfo = annotationInfo_getState (ainfo);
3121 cstring key = metaStateInfo_getName (minfo);
3122 int mvalue = annotationInfo_getValue (ainfo);
3123
3124 sRefSet osrs = sRefSet_undefined;
3125 sRefSet srs;
3126
3127 if (stateClause_isGlobal (cl))
3128 {
3129 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3130 osrs = srs;
3131 }
3132 else
3133 {
3134 srs = stateClause_getRefs (cl);
3135 }
3136
3137 DPRINTF (("Reflect ensures clause: %s", stateClause_unparse (cl)));
3138
3139
3140 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
3141
3142 sRefSet_elements (srs, sel)
3143 {
3144 sRef s;
3145
3146 if (sRef_isResult (sRef_getRootBase (sel)))
3147 {
ccf0a4a8 3148 s = exprNode_getSref (ret);
28bf4b0b 3149 }
3150 else
3151 {
3152 s = sRef_fixBaseParam (sel, args);
28bf4b0b 3153 }
ccf0a4a8 3154
3155 DPRINTF (("Reflecting state clause on: %s / %s",
3156 sRef_unparse (sel), sRef_unparse (s)));
3157
3158 sRef_setMetaStateValueComplete (s, key, mvalue, exprNode_loc (f));
28bf4b0b 3159 } end_sRefSet_elements;
3160
3161 sRefSet_free (osrs);
3162 }
3163 else
3164 {
3165 sRefSet srs = stateClause_getRefs (cl);
3166 sRefModVal modf = stateClause_getEnsuresFunction (cl);
3167 int eparam = stateClause_getStateParameter (cl);
3168
3169 DPRINTF (("Reflect after clause: %s / %s",
3170 stateClause_unparse (cl),
3171 sRefSet_unparse (srs)));
3172
3173 sRefSet_elements (srs, sel)
3174 {
3175 sRef s;
3176
3177 DPRINTF (("elements: %s", sRef_unparse (sel)));
3178 DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3179
3180 if (sRef_isResult (sRef_getRootBase (sel)))
3181 {
ccf0a4a8 3182 DPRINTF (("Fix base: %s / %s",
3183 sRef_unparse (sel), sRef_unparse (exprNode_getSref (ret))));
3184 s = sRef_fixBase (sel, exprNode_getSref (ret));
3185 DPRINTF (("==> %s", sRef_unparseFull (s)));
28bf4b0b 3186 }
3187 else
3188 {
3189 s = sRef_fixBaseParam (sel, args);
28bf4b0b 3190 }
ccf0a4a8 3191
3192 DPRINTF (("elements: %s", sRef_unparse (s)));
3193 DPRINTF (("elements: %s", sRef_unparseFull (s)));
3194
3195 DPRINTF (("Reflecting state clause on: %s / %s",
3196 sRef_unparse (sel), sRef_unparse (s)));
3197
3198 modf (s, eparam, exprNode_loc (f));
28bf4b0b 3199 } end_sRefSet_elements;
3200 }
3201 }
ba45e1e4 3202 } end_stateClauseList_elements ;
3203 }
3204
3205 DPRINTF (("Here: %s / %s",
3206 uentry_unparseFull (le),
3207 bool_unparse (uentry_hasMetaStateEnsures (le))));
3208
3209 if (uentry_hasMetaStateEnsures (le))
3210 {
6970c11b 3211 fileloc loc = exprNode_loc (f);
3212
ccf0a4a8 3213 metaStateConstraintList mscl = uentry_getMetaStateEnsures (le);
3120b462 3214
ccf0a4a8 3215 metaStateConstraintList_elements (mscl, msc)
3120b462 3216 {
ccf0a4a8 3217 metaStateSpecifier msspec = metaStateConstraint_getSpecifier (msc);
3218 metaStateInfo msinfo = metaStateSpecifier_getMetaStateInfo (msspec);
3219 metaStateExpression msexpr = metaStateConstraint_getExpression (msc);
6970c11b 3220 cstring key = metaStateInfo_getName (msinfo);
ccf0a4a8 3221 sRef mlsr = metaStateSpecifier_getSref (msspec);
3222 sRef s;
3223 sRef lastref = sRef_undefined;
3224 stateValue sval = stateValue_undefined;
3225
3226 DPRINTF (("Meta state constraint for %s: %s", uentry_unparse (le),
3227 metaStateConstraint_unparse (msc)));
3228 DPRINTF (("Matches left: %s", sRef_unparseDebug (mlsr)));
3229
3230 if (sRef_isResult (sRef_getRootBase (mlsr)))
12f2ffe9 3231 {
ccf0a4a8 3232 s = exprNode_getSref (ret);
12f2ffe9 3233 }
3234 else
3235 {
ccf0a4a8 3236 s = sRef_fixBaseParam (mlsr, args);
12f2ffe9 3237 }
ccf0a4a8 3238
3239 DPRINTF (("Setting state: %s", sRef_unparseFull (s)));
3240
3241 while (metaStateExpression_isDefined (msexpr))
12f2ffe9 3242 {
ccf0a4a8 3243 metaStateSpecifier ms = metaStateExpression_getSpecifier (msexpr);
ccf0a4a8 3244 metaStateInfo msi = metaStateSpecifier_getMetaStateInfo (ms);
6970c11b 3245 sRef msr, fs;
3246
ccf0a4a8 3247 DPRINTF (("Check expression: %s", metaStateExpression_unparse (msexpr)));
3248
3249 if (metaStateExpression_isMerge (msexpr))
3250 {
3251 msexpr = metaStateExpression_getRest (msexpr);
3252 }
3253 else
3254 {
3255 msexpr = metaStateExpression_undefined;
3256 }
3257
3258 if (metaStateInfo_isDefined (msi))
3259 {
3260 /* Must match lhs state */
3261 llassert (metaStateInfo_equal (msinfo, msi));
3262 }
3263
6970c11b 3264 if (metaStateSpecifier_isElipsis (ms))
12f2ffe9 3265 {
6970c11b 3266 /*
3267 ** For elipsis, we need to merge all the relevant elipsis parameters
3268 **
3269 */
12f2ffe9 3270
6970c11b 3271 uentryList params = uentry_getParams (le);
3272 int paramno = uentryList_size (params) - 1;
3273
3274 if (!uentry_isElipsisMarker (uentryList_getN (params, paramno)))
12f2ffe9 3275 {
6970c11b 3276 voptgenerror
3277 (FLG_TYPE,
3278 message ("Ensures clauses uses ... for function without ... in parameter list: %q",
3279 uentry_getName (le)),
3280 uentry_whereLast (le));
3281 /*@innerbreak@*/ break;
3282 }
3283
3284 while (paramno < exprNodeList_size (args))
3285 {
3286 exprNode arg = exprNodeList_getN (args, paramno);
3287 fs = exprNode_getSref (arg);
3288 DPRINTF (("Merge arg: %s", exprNode_unparse (arg)));
3289
3290 /* cut and pasted... gack*/
3291 if (stateValue_isDefined (sval))
ccf0a4a8 3292 {
6970c11b 3293 /* Use combination table to merge old state value with new one: */
3294 stateValue tval = sRef_getMetaStateValue (fs, key);
ccf0a4a8 3295
6970c11b 3296 if (stateValue_isDefined (tval))
3297 {
3298 stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3299 cstring msg = cstring_undefined;
3300 int nval = stateCombinationTable_lookup (sctable,
3301 stateValue_getValue (sval),
3302 stateValue_getValue (tval),
3303 &msg);
3304 DPRINTF (("Combining: %s + %s -> %d",
3305 stateValue_unparseValue (sval, msinfo),
3306 stateValue_unparseValue (tval, msinfo),
3307 nval));
3308
3309 if (nval == stateValue_error)
3310 {
3311 llassert (cstring_isDefined (msg));
3312
3313 if (optgenerror
3314 (FLG_STATEMERGE,
3315 message
3316 ("Attributes merged in ensures clause in states that "
3317 "cannot be combined (%q is %q, %q is %q): %s",
3318 sRef_unparse (lastref),
3319 stateValue_unparseValue (sval, msinfo),
3320 sRef_unparse (fs),
3321 stateValue_unparseValue (tval, msinfo),
3322 msg),
3323 exprNode_loc (f)))
3324 {
3325 sRef_showMetaStateInfo (fs, key);
3326 }
3327 }
3328
3329 stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3330 loc = exprNode_loc (arg);
3331 }
3332 else
ccf0a4a8 3333 {
6970c11b 3334 DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3335 }
3336 }
3337 else
3338 {
3339 sval = sRef_getMetaStateValue (fs, key);
ccf0a4a8 3340 }
3341
6970c11b 3342 lastref = fs;
3343
3344 if (stateValue_isError (sval))
3345 {
3346 /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3347 }
3348
3349
3350 paramno++;
ccf0a4a8 3351 }
3352 }
3353 else
3354 {
6970c11b 3355 msr = metaStateSpecifier_getSref (ms);
ccf0a4a8 3356
6970c11b 3357
3358 llassert (sRef_isParam (sRef_getRootBase (msr)));
3359 fs = sRef_fixBaseParam (msr, args);
3360
3361 if (stateValue_isDefined (sval))
3362 {
3363 /* Use combination table to merge old state value with new one: */
3364 stateValue tval = sRef_getMetaStateValue (fs, key);
3365
3366 if (stateValue_isDefined (tval))
3367 {
3368 stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3369 cstring msg = cstring_undefined;
3370 int nval = stateCombinationTable_lookup (sctable,
3371 stateValue_getValue (sval),
3372 stateValue_getValue (tval),
3373 &msg);
3374 DPRINTF (("Combining: %s + %s -> %d",
3375 stateValue_unparseValue (sval, msinfo),
3376 stateValue_unparseValue (tval, msinfo),
3377 nval));
3378
3379 if (nval == stateValue_error)
3380 {
3381 llassert (cstring_isDefined (msg));
3382
3383 if (optgenerror
3384 (FLG_STATEMERGE,
3385 message
3386 ("Attributes merged in ensures clause in states that "
3387 "cannot be combined (%q is %q, %q is %q): %s",
3388 sRef_unparse (lastref),
3389 stateValue_unparseValue (sval, msinfo),
3390 sRef_unparse (fs),
3391 stateValue_unparseValue (tval, msinfo),
3392 msg),
3393 exprNode_loc (f)))
3394 {
3395 sRef_showMetaStateInfo (fs, key);
3396 }
3397 }
3398
3399 stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3400 }
3401 else
3402 {
3403 DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3404 }
3405 }
3406 else
3407 {
3408 sval = sRef_getMetaStateValue (fs, key);
3409 }
3410
3411 lastref = fs;
3412
3413 if (stateValue_isError (sval))
3414 {
3415 /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3416 }
12f2ffe9 3417 }
12f2ffe9 3418 }
6970c11b 3419
ccf0a4a8 3420 DPRINTF (("Setting: %s:%s <- %s", sRef_unparse (s), key, stateValue_unparse (sval)));
3421
3422 if (stateValue_isDefined (sval))
12f2ffe9 3423 {
6970c11b 3424 sRef_setMetaStateValueComplete (s, key, stateValue_getValue (sval), loc);
12f2ffe9 3425 }
ccf0a4a8 3426 else
12f2ffe9 3427 {
ccf0a4a8 3428 DPRINTF (("Undefined state: %s", cstring_toCharsSafe (sRef_unparse (s))));
12f2ffe9 3429 }
ccf0a4a8 3430 } end_metaStateConstraintList_elements ;
ba45e1e4 3431
ccf0a4a8 3432 metaStateConstraintList_free (mscl);
28bf4b0b 3433 }
3434 }
3435}
3436
3437static void
3438checkRequiresClause (uentry le, exprNode f, exprNodeList args)
3439{
3440 DPRINTF (("Check requires clause: %s(%s) / %s / %s",
3441 exprNode_unparse (f), exprNodeList_unparse (args),
3442 uentry_unparseFull (le),
3443 stateClauseList_unparse (uentry_getStateClauseList (le))));
3444
3445 if (uentry_isValid (le) && uentry_isFunction (le))
3446 {
3447 stateClauseList sclauses = uentry_getStateClauseList (le);
3448
3449 if (stateClauseList_isDefined (sclauses))
3450 {
3451 DPRINTF (("Check requires: %s / %s / %s",
3452 uentry_unparse (le),
3453 exprNode_unparse (f), exprNodeList_unparse (args)));
3454
3455 stateClauseList_elements (sclauses, cl)
3456 {
3457 DPRINTF (("Check clause: %s / %s",
3458 stateClause_unparse (cl),
3459 bool_unparse (stateClause_hasRequires (cl))));
3460
3461 if (stateClause_hasRequires (cl))
3462 {
3463 sRefSet osrs = sRefSet_undefined;
3464 sRefSet srs;
3465
3466 if (stateClause_isGlobal (cl))
3467 {
3468 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3469 osrs = srs;
3470 }
3471 else
3472 {
3473 srs = stateClause_getRefs (cl);
3474 }
3475
3476 DPRINTF (("Refs: %s", sRefSet_unparse (srs)));
3477
3478 if (stateClause_setsMetaState (cl))
3479 {
3480 qual q = stateClause_getMetaQual (cl);
3481 annotationInfo ainfo = qual_getAnnotationInfo (q);
3482 metaStateInfo minfo = annotationInfo_getState (ainfo);
3483 cstring key = metaStateInfo_getName (minfo);
3484 int mvalue = annotationInfo_getValue (ainfo);
3485
3486 DPRINTF (("Requires meta state! %s = %d", key, mvalue));
3487
3488 sRefSet_elements (srs, sel)
3489 {
3490 sRef s = sRef_fixBaseParam (sel, args);
3491
3492 if (sRef_isResult (sRef_getRootBase (sel)))
3493 {
ccf0a4a8 3494 BADBRANCH;
28bf4b0b 3495 }
3496 else
3497 {
3498 DPRINTF (("Checking state clause on: %s / %s / %s = %d",
3499 sRef_unparseFull (sel), sRef_unparseFull (s),
3500 key, mvalue));
3501
3502 if (!sRef_checkMetaStateValue (s, key, mvalue))
3503 {
3504 DPRINTF (("HERE: %s", sRef_unparse (s)));
3505 if (optgenerror
3506 (FLG_STATETRANSFER,
3507 message
990ec868 3508 ("Requires clause of called function %q not satisfied%q (state is %q): %q",
28bf4b0b 3509 uentry_getName (le),
3510 sRef_isGlobalMarker (s)
3511 ? message ("")
3512 : message (" by %q", sRef_unparse (s)),
3513 stateValue_unparseValue (sRef_getMetaStateValue (s, key),
3514 minfo),
3515 stateClause_unparse (cl)),
3516 exprNode_loc (f)))
3517 {
3518 sRef_showAliasInfo (s);
3519 }
3520 else
3521 {
3522 DPRINTF (("Error supressed!"));
3523 DPRINTF (("Loc: %s", fileloc_unparse (exprNode_loc (f))));
3524 DPRINTF (("Context supress: %s",
3525 bool_unparse (context_suppressFlagMsg (FLG_STATETRANSFER, exprNode_loc (f)))));
3526 }
3527 }
3528 }
3529 } end_sRefSet_elements;
3530 }
3531 else
3532 {
3533 sRefModVal modf = stateClause_getRequiresBodyFunction (cl);
3534 int eparam = stateClause_getStateParameter (cl);
3535
3536 DPRINTF (("Reflect after clause: %s / %s",
3537 stateClause_unparse (cl),
3538 sRefSet_unparse (srs)));
3539
3540 sRefSet_elements (srs, sel)
3541 {
3542 sRef s;
3543
3544 DPRINTF (("elements: %s", sRef_unparse (sel)));
3545 DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3546
3547 s = sRef_fixBaseParam (sel, args);
3548
3549 DPRINTF (("elements: %s", sRef_unparse (s)));
3550 DPRINTF (("elements: %s", sRef_unparseFull (s)));
3551
3552 if (sRef_isResult (sRef_getRootBase (sel)))
3553 {
3554 ; /*@i423 what do we do about results */
3555 }
3556 else
3557 {
3558 DPRINTF (("Reflecting state clause on: %s / %s",
3559 sRef_unparse (sel), sRef_unparse (s)));
3560
3561 modf (s, eparam, exprNode_loc (f));
3562 }
3563 } end_sRefSet_elements;
3564 }
3565
3566 sRefSet_free (osrs);
3567 }
3568 } end_stateClauseList_elements ;
3569 }
3570 }
3571}
3572
616915dd 3573static /*@only@*/ exprNode
3574functionCallSafe (/*@only@*/ /*@notnull@*/ exprNode f,
3575 ctype t, /*@keep@*/ exprNodeList args)
3576{
3577 /* requires f is a non-error exprNode, with type function */
3578 cstring fname = exprNode_unparse (f);
3579 uentry le = exprNode_getUentry (f);
3580 exprNode ret = exprNode_createPartialCopy (f);
3581 int special;
3582
3583 setCodePoint ();
28bf4b0b 3584
3585 DPRINTF (("Call: %s %s",exprNode_unparse (f), exprNodeList_unparse (args)));
3586
3587 ret->typ = ctype_getReturnType (t);
616915dd 3588 ret->kind = XPR_CALL;
3589
3590 ret->edata = exprData_makeCall (f, args);
3591
3592 /*
3593 ** Order of these steps is very important!
3594 **
3595 ** Must check for argument dependencies before messing up uses and sets.
3596 */
3597
3598 if (context_getFlag (FLG_EVALORDER))
3599 {
3600 exprNodeList_elements (args, current)
3601 {
3602 if (exprNode_isDefined (current))
3603 {
3604 exprNode_addUse (current, current->sref);
3605 }
3606 } end_exprNodeList_elements;
3607
3608 if (context_maybeSet (FLG_EVALORDER) || context_maybeSet (FLG_EVALORDERUNCON))
3609 {
3610 checkSequencing (f, args);
3611 }
3612
3613 exprNodeList_elements (args, current)
3614 {
3615 if (exprNode_isDefined (current) && sRef_isMeaningful (current->sref))
3616 {
3617 exprNode_addUse (ret, sRef_makeDerived (current->sref));
3618 }
3619 } end_exprNodeList_elements ;
3620 }
3621
3622 special = checkArgs (le, f, t, args, ret);
3623 checkGlobMods (f, le, args, ret, special);
28bf4b0b 3624 checkRequiresClause (le, f, args);
3625 setCodePoint ();
616915dd 3626
616915dd 3627 if (uentry_isValid (le)
3628 && (uentry_isFunction (le)
3629 || (uentry_isVariable (le)
3630 && ctype_isFunction (uentry_getType (le)))))
3631 {
3632 exitkind exk = uentry_getExitCode (le);
3633
3634 /* f->typ is already set to the return type */
3635
ccf0a4a8 3636 DPRINTF (("Function: %s", uentry_unparseFull (le)));
616915dd 3637 ret->sref = uentry_returnedRef (le, args);
28bf4b0b 3638 DPRINTF (("Returned: %s / %s",
3639 uentry_unparseFull (le),
3640 sRef_unparseFull (ret->sref)));
ccf0a4a8 3641
616915dd 3642 if (uentry_isFunction (le) && exprNodeList_size (args) >= 1)
3643 {
3644 qual nullPred = uentry_nullPred (le);
3645
3646 if (qual_isTrueNull (nullPred))
3647 {
3648 exprNode arg = exprNodeList_head (args);
3649
3650 if (exprNode_isDefined (arg))
3651 {
3652 ret->guards = guardSet_addFalseGuard (ret->guards, arg->sref);
3653 }
3654 }
3655 else if (qual_isFalseNull (nullPred))
3656 {
3657 exprNode arg = exprNodeList_head (args);
3658
3659 if (exprNode_isDefined (arg))
3660 {
3661 ret->guards = guardSet_addTrueGuard (ret->guards, arg->sref);
3662 }
3663 }
3664 else
3665 {
3666 llassert (qual_isUnknown (nullPred));
3667 }
3668 }
3669
3670 if (exitkind_isConditionalExit (exk))
3671 {
3672 /*
3673 ** True exit is:
3674 ** if (arg0) then { exit! } else { ; }
3675 ** False exit is:
3676 ** if (arg0) then { ; } else { exit! }
3677 */
3678
3679 exprNode firstArg;
3680
3681 llassert (!exprNodeList_isEmpty (args));
3682 firstArg = exprNodeList_head (args);
3683
3684 if (exprNode_isDefined (firstArg)
3685 && !guardSet_isEmpty (firstArg->guards))
3686 {
3687 usymtab_trueBranch (guardSet_undefined);
3688 usymtab_altBranch (guardSet_undefined);
3689
3690 if (exitkind_isTrueExit (exk))
3691 {
3692 usymtab_popBranches (firstArg,
3693 exprNode_makeMustExit (),
3694 exprNode_undefined,
3695 TRUE, TRUEEXITCLAUSE);
3696 }
3697 else
3698 {
3699 usymtab_popBranches (firstArg,
3700 exprNode_undefined,
3701 exprNode_makeMustExit (),
3702 TRUE, FALSEEXITCLAUSE);
3703 }
3704 }
3705
3706 ret->exitCode = XK_MAYEXIT;
3707 }
3708 else if (exitkind_mustExit (exk))
3709 {
3710 ret->exitCode = XK_MUSTEXIT;
3711 }
3712 else if (exitkind_couldExit (exk))
3713 {
3714 ret->exitCode = XK_MAYEXIT;
3715 }
3716 else
3717 {
3718 ;
3719 }
3720
3721 if (cstring_equalLit (fname, "exit"))
3722 {
3723 if (exprNodeList_size (args) == 1)
3724 {
3725 exprNode arg = exprNodeList_head (args);
3726
3727 if (exprNode_isDefined (arg) && exprNode_knownIntValue (arg))
3728 {
3729 long int val = multiVal_forceInt (exprNode_getValue (arg));
3730
3731 if (val != 0)
3732 {
3733 voptgenerror
3734 (FLG_EXITARG,
3735 message
3736 ("Argument to exit has implementation defined behavior: %s",
3737 exprNode_unparse (arg)),
3738 exprNode_loc (arg));
3739 }
3740 }
3741 }
3742 }
3743 }
3744 else
3745 {
3746 ret->sref = defref;
3747 exprNode_checkSetAny (ret, uentry_rawName (le));
3748 }
3749
ccf0a4a8 3750 DPRINTF (("Before reflect: %s", sRef_unparseFull (ret->sref)));
3751 DPRINTF (("Reflect: %s", uentry_unparseFull (le)));
3752 reflectEnsuresClause (ret, le, f, args);
3753 setCodePoint ();
3754
616915dd 3755 return (ret);
3756}
3757
3758/*
3759** this is yucky! should keep the uentry as part of exprNode!
3760*/
3761
3762/*@observer@*/ uentry
3763exprNode_getUentry (exprNode e)
3764{
3765 if (exprNode_isError (e))
3766 {
3767 return uentry_undefined;
3768 }
3769 else
3770 {
3771 cstring s = exprNode_rootVarName (e);
3772 uentry ue = usymtab_lookupSafe (s);
3773
3774 return ue;
3775 }
3776}
3777
3778exprNode
3779exprNode_makeInitBlock (lltok brace, /*@only@*/ exprNodeList inits)
3780{
3781 exprNode ret = exprNode_createPlain (ctype_unknown);
3782
3783 ret->kind = XPR_INITBLOCK;
3784 ret->edata = exprData_makeCall (exprNode_undefined, inits);
3785 ret->loc = fileloc_update (ret->loc, lltok_getLoc (brace));
3786
3787 return (ret);
3788}
3789
3790exprNode
3791exprNode_functionCall (/*@only@*/ exprNode f, /*@only@*/ exprNodeList args)
3792{
3793 ctype t;
3794
3795 setCodePoint ();
3796
3797 if (exprNode_isUndefined (f))
3798 {
3799 exprNode_free (f);
3800 exprNodeList_free (args);
3801 return exprNode_undefined;
3802 }
3803
3804 t = exprNode_getType (f);
3805
3806 if (sRef_isLocalVar (f->sref))
3807 {
3808 exprNode_checkUse (f, f->sref, f->loc);
3809
3810 if (sRef_possiblyNull (f->sref))
3811 {
3812 if (!usymtab_isGuarded (f->sref))
3813 {
3814 if (optgenerror (FLG_NULLDEREF,
3815 message ("Function call using %s pointer %q",
3816 sRef_nullMessage (f->sref),
3817 sRef_unparse (f->sref)),
3818 f->loc))
3819 {
3820 sRef_showNullInfo (f->sref);
3821 sRef_setNullError (f->sref);
3822 }
3823 }
3824 }
3825 }
3826
3827 setCodePoint ();
3828
3829 if (ctype_isRealFunction (t))
3830 {
3831 exprNode ret = functionCallSafe (f, t, args);
3832 setCodePoint ();
3833 return ret;
3834 }
3835 else if (ctype_isUnknown (t))
3836 {
3837 exprNode ret = exprNode_createPartialCopy (f);
3838 cstring tstring;
3839
3840 setCodePoint ();
3841
3842 ret->typ = t;
3843 exprNodeList_elements (args, current)
3844 {
3845 if (exprNode_isDefined (current))
3846 {
3847 exprNode_checkUse (ret, current->sref, ret->loc);
3848
3849 /*
3850 ** also, anything derivable from current->sref may be used
3851 */
3852
3853 exprNode_addUse (ret, sRef_makeDerived (current->sref));
3854 exprNode_mergeUSs (ret, current);
3855 }
3856 } end_exprNodeList_elements;
3857
3858 ret->edata = exprData_makeCall (f, args);
3859 ret->kind = XPR_CALL;
3860
3861 tstring = cstring_copy (exprNode_unparse (f));
3862
3863 cstring_markOwned (tstring);
3864 exprNode_checkSetAny (ret, tstring);
3865
3866 return (ret);
3867 }
3868 else
3869 {
3870 voptgenerror (FLG_TYPE,
3871 message ("Call to non-function (type %t): %s", t,
3872 exprNode_unparse (f)),
3873 f->loc);
3874 exprNode_free (f);
3875 exprNodeList_free (args);
3876
3877 return (exprNode_makeError ());
3878 }
3879}
3880
28bf4b0b 3881static exprNode
3882exprNode_fieldAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
3883 /*@only@*/ cstring f)
616915dd 3884{
3885 exprNode ret = exprNode_createPartialCopy (s);
3886
3887 ret->kind = XPR_FACCESS;
3888
3889 if (exprNode_isError (s))
3890 {
3891 ret->edata = exprData_makeField (s, f);
3892 return ret;
3893 }
3894 else
3895 {
3896 ctype t = exprNode_getType (s);
3897 ctype tr = ctype_realType (t);
28bf4b0b 3898
616915dd 3899 checkMacroParen (s);
3900
3901 ret->edata = exprData_makeField (s, f);
28bf4b0b 3902
616915dd 3903 if (ctype_isStructorUnion (tr))
3904 {
3905 uentry tf = uentryList_lookupField (ctype_getFields (tr), f);
3906
3907 if (uentry_isUndefined (tf))
3908 {
3909 voptgenerror (FLG_TYPE,
3910 message ("Access non-existent field %s of %t: %s", f, t,
3911 exprNode_unparse (ret)),
28bf4b0b 3912 loc);
3913 /*! cstring_free (f); */ /* evans 2001-03-25 self-detect */
616915dd 3914 return (ret);
3915 }
3916 else
3917 {
3918 uentry_setUsed (tf, exprNode_loc (ret));
3919
3920 ret->typ = uentry_getType (tf);
3921 checkSafeUse (ret, s->sref);
3922
3923 ret->sref = sRef_makeField (s->sref, uentry_rawName (tf));
28bf4b0b 3924 /*!? exprNode_free (s); */ /* evans 2001-03-25 self-detect */
616915dd 3925 return (ret);
3926 }
3927 }
3928 else /* isStructorUnion */
3929 {
3930 if (ctype_isRealAbstract (tr))
3931 {
3932 voptgenerror
3933 (FLG_ABSTRACT,
3934 message ("Access field of abstract type (%t): %s.%s",
3935 t, exprNode_unparse (s), f),
28bf4b0b 3936 loc);
616915dd 3937 ret->typ = ctype_unknown;
3938 }
3939 else
3940 {
3941 if (ctype_isKnown (tr))
3942 {
3943 voptgenerror
3944 (FLG_TYPE,
3945 message
3946 ("Access field of non-struct or union (%t): %s.%s",
3947 t, exprNode_unparse (s), f),
28bf4b0b 3948 loc);
616915dd 3949
3950 ret->typ = ctype_unknown;
3951 }
3952 else
3953 {
3954 cstring sn = cstring_copy (f);
28bf4b0b 3955
616915dd 3956 checkSafeUse (ret, s->sref);
3957 cstring_markOwned (sn);
3958 ret->sref = sRef_makeField (s->sref, sn);
616915dd 3959 return (ret);
3960 }
3961 }
28bf4b0b 3962
616915dd 3963 return (ret);
3964 }
3965 }
3966 BADEXIT;
3967}
3968
28bf4b0b 3969exprNode
3970exprNode_fieldAccess (/*@only@*/ exprNode s, /*@only@*/ lltok dot,
3971 /*@only@*/ cstring f)
3972{
3973 exprNode res = exprNode_fieldAccessAux (s, lltok_getLoc (dot), f);
3974 lltok_release (dot);
3975 return res;
3976}
3977
616915dd 3978exprNode
3979exprNode_addParens (/*@only@*/ lltok lpar, /*@only@*/ exprNode e)
3980{
3981 exprNode ret = exprNode_createPartialCopy (e);
3982
3983 ret->loc = fileloc_update (ret->loc, lltok_getLoc (lpar));
3984 ret->kind = XPR_PARENS;
3985 ret->edata = exprData_makeUop (e, lpar);
3986
3987 if (!exprNode_isError (e))
3988 {
3989 ret->exitCode = e->exitCode;
3990 ret->canBreak = e->canBreak;
3991 ret->mustBreak = e->mustBreak;
3992 ret->isJumpPoint = e->isJumpPoint;
3993 ret->sref = e->sref;
3994 }
3995
3996 return ret;
3997}
3998
28bf4b0b 3999static exprNode
4000exprNode_arrowAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
4001 /*@only@*/ cstring f)
616915dd 4002{
4003 exprNode ret = exprNode_createPartialCopy (s);
4004
4005 ret->edata = exprData_makeField (s, f);
4006 ret->kind = XPR_ARROW;
28bf4b0b 4007
616915dd 4008 if (exprNode_isError (s))
4009 {
4010 return (ret);
4011 }
4012 else
4013 {
28bf4b0b 4014 ctype t = exprNode_getType (s);
4015 ctype tr = ctype_realType (t);
4016
4017 checkMacroParen (s);
4018
4019 (void) ctype_fixArrayPtr (tr); /* REWRITE THIS */
4020
4021 if (ctype_isRealPointer (tr))
4022 {
4023 ctype b = ctype_realType (ctype_baseArrayPtr (tr));
4024
4025 if (ctype_isStructorUnion (b))
4026 {
4027 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4028
4029 if (sRef_isKnown (s->sref) && sRef_possiblyNull (s->sref))
4030 {
4031 if (!usymtab_isGuarded (s->sref) && !context_inProtectVars ())
4032 {
4033 if (optgenerror
4034 (FLG_NULLDEREF,
4035 message ("Arrow access from %s pointer%q: %s",
4036 sRef_nullMessage (s->sref),
4037 sRef_unparsePreOpt (s->sref),
4038 exprNode_unparse (ret)),
4039 loc))
4040 {
4041 sRef_showNullInfo (s->sref);
4042 sRef_setNullError (s->sref);
4043 }
4044 }
4045 }
4046
4047 if (uentry_isUndefined (fentry))
4048 {
4049 voptgenerror
4050 (FLG_TYPE,
4051 message ("Access non-existent field %s of %t: %s",
4052 f, t, exprNode_unparse (ret)),
4053 loc);
4054 ret->typ = ctype_unknown;
4055 return (ret);
4056 }
4057 else
4058 {
4059 /*
4060 ** was safeUse: shouldn't be safe!
4061 **
4062 ** to do rec->field
4063 ** rec must be defined,
4064 ** *rec must be allocated
4065 ** rec->field need only be defined it if is an rvalue
4066 */
4067
4068 uentry_setUsed (fentry, exprNode_loc (ret));
4069 ret->typ = uentry_getType (fentry);
4070
4071 exprNode_checkUse (ret, s->sref, s->loc);
4072
4073 /* exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc); */
4074 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4075 return (ret);
4076 }
4077 }
4078 else /* Pointer to something that is not a struct or union*/
4079 {
4080 if (ctype_isRealAbstract (tr))
4081 {
4082 ctype xrt = ctype_forceRealType (tr);
4083
4084 voptgenerror
4085 (FLG_ABSTRACT,
4086 message ("Arrow access field of abstract type (%t): %s->%s",
4087 t, exprNode_unparse (s), f),
4088 loc);
4089
4090 /*
4091 ** Set the state correctly, as if the abstraction is broken.
4092 */
4093
4094 if (ctype_isRealPointer (xrt) &&
4095 (b = ctype_realType (ctype_baseArrayPtr (xrt)),
4096 ctype_isStructorUnion (b)))
4097 {
4098 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4099 ret->typ = uentry_getType (fentry);
4100 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4101 }
4102 else
4103 {
4104 ret->typ = ctype_unknown;
4105 ret->sref = sRef_undefined;
4106 }
4107 }
4108 else /* not a struct, union or abstract */
4109 {
4110 if (ctype_isUnknown (tr)) {
4111 cstring sn = cstring_copy (f);
4112
4113 DPRINTF (("Here: %s", exprNode_unparse (s)));
4114
4115 exprNode_checkUse (ret, s->sref, s->loc);
4116 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4117
4118 cstring_markOwned (sn);
4119 ret->sref = sRef_makeArrow (s->sref, sn);
4120
4121 ret->kind = XPR_ARROW;
4122 return (ret);
4123 } else {
4124 voptgenerror
4125 (FLG_TYPE,
4126 message ("Arrow access field of non-struct or union "
4127 "pointer (%t): %s->%s",
4128 t, exprNode_unparse (s), f),
4129 loc);
4130
4131 ret->typ = ctype_unknown;
4132 ret->sref = sRef_undefined;
4133 }
4134 }
4135 }
4136 }
4137 else /* its not a pointer */
4138 {
4139 if (!ctype_isUnknown (tr))
4140 {
4141 voptgenerror
4142 (FLG_TYPE,
4143 message ("Arrow access of non-pointer (%t): %s->%s",
4144 t, exprNode_unparse (s), f),
4145 loc);
4146
4147 ret->typ = ctype_unknown;
4148 ret->sref = sRef_undefined;
4149 }
4150 else
4151 {
4152 cstring sn = cstring_copy (f);
4153
4154 DPRINTF (("Here: %s", exprNode_unparse (s)));
4155
4156 exprNode_checkUse (ret, s->sref, s->loc);
4157 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4158
4159 cstring_markOwned (sn);
4160 ret->sref = sRef_makeArrow (s->sref, sn);
4161
4162 ret->kind = XPR_ARROW;
4163 return (ret);
4164 }
4165 }
4166
616915dd 4167 return (ret);
4168 }
4169 BADEXIT;
4170}
4171
28bf4b0b 4172exprNode
4173exprNode_arrowAccess (/*@only@*/ exprNode s,
4174 /*@only@*/ lltok arrow,
4175 /*@only@*/ cstring f)
4176{
4177 exprNode res = exprNode_arrowAccessAux (s, lltok_getLoc (arrow), f);
4178 lltok_release (arrow);
4179 return res;
4180}
4181
616915dd 4182/*
4183** only postOp's in C: i++ and i--
4184*/
4185
4186exprNode
4187exprNode_postOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4188{
4189 /* check modification also */
4190 /* cstring opname = lltok_unparse (op);*/
4191 ctype t;
4192 exprNode ret = exprNode_createPartialCopy (e);
4193
4194 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4195 ret->kind = XPR_POSTOP;
4196 ret->edata = exprData_makeUop (e, op);
4197
4198 if (!exprNode_isDefined (e))
4199 {
4200 return ret;
4201 }
4202
4203 checkMacroParen (e);
4204
4205 exprNode_checkUse (ret, e->sref, e->loc);
4206 exprNode_checkSet (ret, e->sref);
4207
4208 t = exprNode_getType (e);
4209
4210 if (sRef_isUnsafe (e->sref))
4211 {
4212 voptgenerror (FLG_MACROPARAMS,
4213 message ("Operand of %s is macro parameter (non-functional): %s%s",
4214 lltok_unparse (op), exprNode_unparse (e), lltok_unparse (op)),
4215 e->loc);
4216 sRef_makeSafe (e->sref);
4217 sRef_makeSafe (ret->sref);
4218 }
4219
4220 if (ctype_isForceRealNumeric (&t) || ctype_isRealAP (t))
4221 {
4222 ret->typ = e->typ;
4223 }
4224 else
4225 {
4226 if (ctype_isRealAbstract (t))
4227 {
4228 voptgenerror
4229 (FLG_ABSTRACT,
4230 message ("Operand of %s is abstract type (%t): %s",
4231 lltok_unparse (op), t, exprNode_unparse (e)),
4232 e->loc);
4233 }
4234 else
4235 {
4236 voptgenerror
4237 (FLG_TYPE,
4238 message ("Operand of %s is non-numeric (%t): %s",
4239 lltok_unparse (op), t, exprNode_unparse (e)),
4240 e->loc);
4241 }
4242 ret->typ = ctype_unknown;
4243 }
4244
4245 /* if (ctype_isZero (t)) e->typ = ctype_int; */
4246
4247 exprNode_checkModify (e, ret);
4248
4249 /* added 7/11/2000 D.L */
84c9ffbf 4250 /*@i223*/
4251 /*DRL 6/8/01 I decided to disable all LCLint Warning here since the code
4252 probably needs a rewrite any way */
4253
4254 /*@ignore@*/
4255
dc92450f 4256 // updateEnvironmentForPostOp (e);
616915dd 4257
4258 /* start modifications */
4259 /* added by Seejo on 4/16/2000 */
4260
4261 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4262 status */
4263 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4264
4265 ret->sref = sRef_copy (e->sref);
4266
4267 /* Operator : ++ */
4268 if (lltok_getTok (op) == INC_OP) {
4269 if (sRef_getSize(e->sref) > 0) {
4270
4271 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4272
4273 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4274 /* Assumption: there is only 1 \0 in the buffer */
4275 /* This will not be correct if there are 2 \0's in the buffer */
4276 sRef_setNotNullTerminatedState(ret->sref);
4277 sRef_resetLen(ret->sref);
4278 } else {
4279 sRef_setNullTerminatedState(ret->sref);
4280 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4281 }
4282 if (sRef_isNullTerminated (ret->sref))
4283 printf ("ret->sref is Null Terminated\n");
4284 else if (sRef_isPossiblyNullTerminated (ret->sref))
4285 printf ("ret->sref is Possibly Null Terminated\n");
4286 else if (sRef_isNotNullTerminated (ret->sref))
4287 printf ("ret->sref is Not Null Terminated\n");
4288 }
4289 }
4290
4291 /* Operator : -- */
4292 if (lltok_getTok (op) == DEC_OP) {
4293 if (sRef_getSize(e->sref) >= 0) {
4294 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4295 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4296 }
4297 }
4298 }
84c9ffbf 4299 /*@end@*/
616915dd 4300 /* end modifications */
4301
4302 return ret;
4303}
4304
4305exprNode
4306exprNode_preOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4307{
4308 bool checkMod = FALSE;
4309 ctype te, tr;
4310 int opid = lltok_getTok (op);
4311 exprNode ret = exprNode_createSemiCopy (e);
4312
4313 exprNode_copySets (ret, e);
4314
4315 multiVal_free (ret->val);
4316 ret->val = multiVal_undefined;
4317 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4318 ret->kind = XPR_PREOP;
4319 ret->edata = exprData_makeUop (e, op);
4320
4321 if (exprNode_isError (e))
4322 {
4323 return ret;
4324 }
4325
4326 checkMacroParen (e);
4327
4328 te = exprNode_getType (e);
4329 tr = ctype_realType (te);
4330
4331 if (opid != TAMPERSAND)
4332 {
4333 exprNode_checkUse (ret, e->sref, e->loc);
4334
4335 if (ctype_isRealAbstract (tr)
4336 && (!(ctype_isRealBool (te) && (opid == TEXCL))))
4337 {
4338 if (optgenerror (FLG_ABSTRACT,
4339 message ("Operand of %s is abstract type (%t): %s",
4340 lltok_unparse (op), tr,
4341 exprNode_unparse (ret)),
4342 e->loc))
4343 {
4344 tr = te = ctype_unknown;
4345 ret->typ = ctype_unknown;
4346 sRef_setNullError (e->sref);
4347 }
4348 }
4349 }
4350
4351 switch (opid)
4352 {
4353 case INC_OP:
4354 case DEC_OP: /* should also check modification! */
616915dd 4355 if (sRef_isMacroParamRef (e->sref))
4356 {
4357 voptgenerror
4358 (FLG_MACROPARAMS,
4359 message ("Operand of %s is macro parameter (non-functional): %s",
4360 lltok_unparse (op), exprNode_unparse (ret)),
4361 e->loc);
4362 }
4363 else
4364 {
4365 exprNode_checkSet (ret, e->sref);
4366 }
4367
4368 if (ctype_isForceRealNumeric (&tr) || ctype_isRealAP (tr))
4369 {
4370 }
4371 else
4372 {
4373 if (context_msgStrictOps ())
4374 {
4375 voptgenerror
4376 (FLG_STRICTOPS,
4377 message ("Operand of %s is non-numeric (%t): %s",
4378 lltok_unparse (op), te, exprNode_unparse (ret)),
4379 e->loc);
4380 }
4381 ret->typ = ctype_int;
4382 }
4383
4384 /* start modifications */
4385 /* added by Seejo on 4/16/2000 */
4386
4387 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4388 status */
4389 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4390
4391 ret->sref = sRef_copy (e->sref);
4392
4393 /* Operator : ++ */
4394 if (lltok_getTok (op) == INC_OP) {
4395 if (sRef_getSize(e->sref) > 0) {
4396
4397 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4398
4399 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4400 /* Assumption: there is only 1 \0 in the buffer */
4401 /* This will not be correct if there are 2 \0's in the buffer */
4402 sRef_setNotNullTerminatedState(ret->sref);
4403 sRef_resetLen (ret->sref);
4404 } else {
4405 sRef_setNullTerminatedState(ret->sref);
4406 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4407 }
4408 }
4409 }
4410
4411 /* Operator : -- */
4412 if (lltok_getTok (op) == DEC_OP) {
4413 if (sRef_getSize(e->sref) >= 0) {
4414 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4415 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4416 }
4417 }
4418 }
4419
4420 /* end modifications */
4421
4422 checkMod = TRUE;
4423 break;
4424
4425 case TMINUS:
4426 case TPLUS:
4427 if (ctype_isForceRealNumeric (&tr))
4428 {
4429 if (opid == TMINUS)
4430 {
4431 ret->val = multiVal_invert (exprNode_getValue (e));
4432 }
4433 else
4434 {
4435 ret->val = multiVal_copy (exprNode_getValue (e));
4436 }
4437 }
4438 else
4439 {
4440 if (context_msgStrictOps ())
4441 {
4442 voptgenerror
4443 (FLG_STRICTOPS,
4444 message ("Operand of %s is non-numeric (%t): %s",
4445 lltok_unparse (op), te, exprNode_unparse (ret)),
4446 e->loc);
4447 }
4448
4449 ret->typ = ctype_int;
4450 }
4451 break;
4452
4453 case TEXCL: /* maybe this should be restricted */
4454 guardSet_flip (ret->guards);
4455
28bf4b0b 4456 if (ctype_isRealBool (te) || ctype_isUnknown (te))
616915dd 4457 {
4458 ;
4459 }
4460 else
4461 {
4462 if (ctype_isRealPointer (tr))
4463 {
4464 if (sRef_isKnown (e->sref))
4465 {
4466 ret->guards = guardSet_addFalseGuard (ret->guards, e->sref);
4467 }
28bf4b0b 4468
616915dd 4469 voptgenerror2n
4470 (FLG_BOOLOPS, FLG_PTRNEGATE,
4471 message ("Operand of %s is non-boolean (%t): %s",
4472 lltok_unparse (op), te, exprNode_unparse (ret)),
4473 e->loc);
4474 }
4475 else
4476 {
4477 voptgenerror
4478 (FLG_BOOLOPS,
4479 message ("Operand of %s is non-boolean (%t): %s",
4480 lltok_unparse (op), te, exprNode_unparse (ret)),
4481 e->loc);
4482 }
4483
4484 ret->typ = ctype_bool;
4485 }
4486 break;
4487
4488 case TTILDE:
4489 if (ctype_isForceRealInt (&tr))
4490 {
4491 }
4492 else
4493 {
4494 if (context_msgStrictOps ())
4495 {
4496 voptgenerror
4497 (FLG_STRICTOPS,
4498 message ("Operand of %s is non-integer (%t): %s",
4499 lltok_unparse (op), te, exprNode_unparse (ret)),
4500 e->loc);
4501 }
4502
4503 if (ctype_isInt (e->typ))
4504 {
4505 ret->typ = e->typ;
4506 }
4507 else
4508 {
4509 ret->typ = ctype_int;
4510 }
4511 }
4512 break;
4513
4514 case TAMPERSAND:
4515 ret->typ = ctype_makePointer (e->typ);
4516
4517 if (sRef_isKnown (e->sref))
4518 {
4519 ret->sref = sRef_makeAddress (e->sref);
4520 }
4521
4522 break;
4523
4524 case TMULT:
4525
4526 if (ctype_isAP (tr))
4527 {
4528 ret->typ = ctype_baseArrayPtr (e->typ);
4529 }
4530 else
4531 {
4532 if (ctype_isKnown (te))
4533 {
4534 if (ctype_isFunction (te))
4535 {
4536 ret->typ = e->typ;
4537
4538 voptgenerror
4539 (FLG_FCNDEREF,
4540 message ("Dereference of function type (%t): %s",
4541 te, exprNode_unparse (ret)),
4542 e->loc);
4543 }
4544 else
4545 {
4546 voptgenerror (FLG_TYPE,
4547 message ("Dereference of non-pointer (%t): %s",
4548 te, exprNode_unparse (ret)),
4549 e->loc);
4550 ret->typ = ctype_unknown;
4551 }
4552 }
4553 else
4554 {
4555 ret->typ = ctype_unknown;
4556 }
4557
4558 }
4559
4560 if (sRef_isKnown (e->sref))
4561 {
4562 if (sRef_possiblyNull (e->sref))
4563 {
4564 if (!usymtab_isGuarded (e->sref) && !context_inProtectVars ())
4565 {
4566 if (optgenerror
4567 (FLG_NULLDEREF,
4568 message ("Dereference of %s pointer %q: %s",
4569 sRef_nullMessage (e->sref),
4570 sRef_unparse (e->sref),
4571 exprNode_unparse (ret)),
4572 e->loc))
4573 {
4574 sRef_showNullInfo (e->sref);
4575 sRef_setNotNull (e->sref, e->loc); /* suppress future messages */
4576 }
4577 }
4578 }
4579
4580 ret->sref = sRef_makePointer (e->sref);
4581 }
4582 break;
4583
4584 default:
4585 llbug (message ("exprNode_preOp: unhandled op: %s", lltok_unparse (op)));
4586 }
4587
4588 if (checkMod)
4589 {
4590 exprNode_checkModify (e, ret);
4591 }
4592
4593 return ret;
4594}
4595
4596/*
4597** any reason to disallow sizeof (abstract type) ?
4598*/
4599
4600/*
4601** used by both sizeof
4602*/
4603
4604static
4605ctype sizeof_resultType (void)
4606{
4607 static ctype sizet = ctype_unknown;
4608
4609 if (ctype_isUnknown (sizet))
4610 {
4611 if (usymtab_existsType (cstring_makeLiteralTemp ("size_t")))
4612 {
4613 sizet = uentry_getAbstractType (usymtab_lookup (cstring_makeLiteralTemp ("size_t")));
4614 }
4615 else
4616 {
4617 sizet = ctype_ulint;
4618 }
4619 }
4620 return sizet;
4621}
4622
4623exprNode
4624exprNode_sizeofType (/*@only@*/ qtype qt)
4625{
4626 exprNode ret = exprNode_create (sizeof_resultType ());
4627 ctype ct = qtype_getType (qt);
4628
4629 ret->kind = XPR_SIZEOFT;
4630 ret->edata = exprData_makeSizeofType (qt);
4631
4632 voptgenerror (FLG_SIZEOFTYPE,
4633 message ("Parameter to sizeof is type %s: %s",
4634 ctype_unparse (ct),
4635 exprNode_unparse (ret)),
4636 ret->loc);
4637
4638 return (ret);
4639}
4640
4641exprNode
4642exprNode_alignofType (/*@only@*/ qtype qt)
4643{
4644 exprNode ret = exprNode_create (sizeof_resultType ());
4645 ctype ct = qtype_getType (qt);
4646
4647 ret->kind = XPR_ALIGNOFT;
4648 ret->edata = exprData_makeSizeofType (qt);
4649
4650 voptgenerror (FLG_SIZEOFTYPE,
4651 message ("Parameter to alignof is type %s: %s",
4652 ctype_unparse (ct),
4653 exprNode_unparse (ret)),
4654 ret->loc);
4655
4656 return (ret);
4657}
4658
4659exprNode exprNode_offsetof (qtype qt, cstringList s)
4660{
4661 exprNode ret = exprNode_create (sizeof_resultType ());
4662 ctype ct = qtype_getType (qt);
4663
4664 ret->kind = XPR_OFFSETOF;
4665 ret->edata = exprData_makeOffsetof (qt, s);
4666
4667 if (!ctype_isRealSU (ct))
4668 {
4669 voptgenerror (FLG_TYPE,
4670 message ("First parameter to offsetof is not a "
4671 "struct or union type (type %s): %s",
4672 ctype_unparse (ct),
4673 exprNode_unparse (ret)),
4674 ret->loc);
4675 }
4676 else
4677 {
4678 ctype lt = ct;
4679
4680 cstringList_elements (s, el) {
4681 uentryList fields;
4682 uentry fld;
4683
4684 if (ctype_isUndefined (lt))
4685 {
4686 break;
4687 }
4688 else if (!ctype_isRealSU (lt))
4689 {
4690 voptgenerror (FLG_TYPE,
4691 message ("Inner offsetof type is not a "
4692 "struct or union type (type %s before field %s): %s",
4693 ctype_unparse (lt), el,
4694 exprNode_unparse (ret)),
4695 ret->loc);
4696 break;
4697 }
4698 else
4699 {
4700 fields = ctype_getFields (ctype_realType (lt));
4701 fld = uentryList_lookupField (fields, el);
4702 DPRINTF (("Try: %s / %s", ctype_unparse (lt), el));
4703
4704 if (uentry_isUndefined (fld))
4705 {
4706 if (ctype_equal (lt, ct)) {
4707 voptgenerror (FLG_TYPE,
4708 message ("Field %s in offsetof is not the "
4709 "name of a field of %s: %s",
4710 el,
4711 ctype_unparse (ct),
4712 exprNode_unparse (ret)),
4713 ret->loc);
4714 } else {
4715 voptgenerror (FLG_TYPE,
4716 message ("Deep field %s in offsetof is not the "
4717 "name of a field of %s: %s",
4718 el,
4719 ctype_unparse (lt),
4720 exprNode_unparse (ret)),
4721 ret->loc);
4722 }
4723 }
4724 else
4725 {
4726 lt = uentry_getType (fld);
4727 }
4728 }
4729 } end_cstringList_elements;
4730
4731 /* Should report error if its a bit field - behavior is undefined! */
4732 }
4733
4734 return (ret);
4735}
4736
4737/*@only@*/ exprNode
4738exprNode_sizeofExpr (/*@only@*/ exprNode e)
4739{
4740 exprNode ret;
4741
4742 if (exprNode_isUndefined (e))
4743 {
4744 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4745 ret->edata = exprData_makeSingle (e);
4746 ret->typ = sizeof_resultType ();
4747 ret->kind = XPR_SIZEOF;
4748 }
4749 else
4750 {
4751 uentry u = exprNode_getUentry (e);
4752
4753 ret = exprNode_createPartialCopy (e);
4754 ret->edata = exprData_makeSingle (e);
4755
4756 ret->typ = sizeof_resultType ();
4757 ret->kind = XPR_SIZEOF;
4758
4759 if (uentry_isValid (u)
4760 && uentry_isRefParam (u)
4761 && ctype_isRealArray (uentry_getType (u)))
4762 {
4763 voptgenerror
4764 (FLG_SIZEOFFORMALARRAY,
4765 message ("Parameter to sizeof is an array-type function parameter: %s",
4766 exprNode_unparse (ret)),
4767 ret->loc);
4768 }
4769 }
4770
4771 /*
4772 ** sizeof (x) doesn't "really" use x
4773 */
4774
4775 return (ret);
4776}
4777
4778/*@only@*/ exprNode
4779exprNode_alignofExpr (/*@only@*/ exprNode e)
4780{
4781 exprNode ret;
4782
4783 if (exprNode_isUndefined (e))
4784 {
4785 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4786 }
4787 else
4788 {
4789 ret = exprNode_createPartialCopy (e);
4790 }
4791
4792 ret->edata = exprData_makeSingle (e);
4793 ret->typ = sizeof_resultType ();
4794 ret->kind = XPR_ALIGNOF;
4795
4796 /*
4797 ** sizeof (x) doesn't "really" use x
4798 */
4799
4800 return (ret);
4801}
4802
4803/*@only@*/ exprNode
4804exprNode_cast (/*@only@*/ lltok tok, /*@only@*/ exprNode e, /*@only@*/ qtype q)
4805{
4806 ctype c;
4807 ctype t;
4808 exprNode ret;
4809
4810 if (exprNode_isError (e))
4811 {
4812 qtype_free (q);
4813 lltok_release (tok);
4814 return exprNode_undefined;
4815 }
4816
4817 checkMacroParen (e);
4818
4819 c = qtype_getType (q);
4820 t = exprNode_getType (e);
4821
4822 ret = exprNode_createPartialCopy (e);
4823
4824 ret->loc = fileloc_update (ret->loc, lltok_getLoc (tok));
4825 ret->typ = c;
4826 ret->kind = XPR_CAST;
4827 ret->edata = exprData_makeCast (tok, e, q);
4828
4829 if (ctype_isRealSU (ctype_getBaseType (sRef_getType (e->sref))))
4830 {
4831 /*
4832 ** This is a bit of a hack to avoid a problem
4833 ** when the code does,
4834 ** (some other struct) x
4835 ** ...
4836 ** x->field
4837 */
4838
4839 ret->sref = sRef_copy (e->sref);
4840 usymtab_addForceMustAlias (ret->sref, e->sref);
4841 sRef_setTypeFull (ret->sref, c);
4842 DPRINTF (("Cast: %s -> %s", sRef_unparseFull (e->sref),
4843 sRef_unparseFull (ret->sref)));
4844 }
4845 else
4846 {
4847 ret->sref = e->sref;
4848 sRef_setTypeFull (ret->sref, c);
4849 DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref)));
4850 }
4851
4852 /*
4853 ** we allow
4854 ** abstract -> void
4855 ** 0 <-> abstract *
4856 ** void * <-> abstract * (if FLG_ABSTVOIDP)
4857 ** abstract * <-> void * (if FLG_ABSTVOIDP)
4858 */
4859
4860 if (ctype_isVoid (c)) /* cast to void is always okay --- discard value */
4861 {
4862 ;
4863 }
4864 else if (ctype_isRealAP (c)) /* casting to array or pointer */
4865 {
4866 ctype bc = ctype_getBaseType (c);
4867 ctype bt = ctype_getBaseType (t);
4868 ctype rt = ctype_realType (t);
4869
4870 if (ctype_isFunction (ctype_baseArrayPtr (ctype_realType (c)))
4871 && (ctype_isArrayPtr (rt)
4872 && !ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
4873 {
4874 voptgenerror
4875 (FLG_CASTFCNPTR,
4876 message ("Cast from function pointer type (%t) to "
4877 "non-function pointer (%t): %s",
4878 c, t, exprNode_unparse (ret)),
4879 e->loc);
4880 }
4881
4882 if (!ctype_isFunction (ctype_baseArrayPtr (c))
4883 && (ctype_isArrayPtr (rt)
4884 && ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
4885 {
4886 voptgenerror
4887 (FLG_CASTFCNPTR,
4888 message ("Cast from non-function pointer type (%t) to "
4889 "function pointer (%t): %s",
4890 c, t, exprNode_unparse (ret)),
4891 e->loc);
4892 }
4893
4894 if (exprNode_isZero (e) && context_getFlag (FLG_ZEROPTR) &&
4895 !(ctype_isRealAbstract (bc)
4896 && context_hasAccess (ctype_typeId (bc))))
4897 {
4898 ; /* okay to cast zero */
4899 }
4900 else
4901 {
4902 if (ctype_isRealAbstract (bc)
4903 && !context_hasAccess (ctype_typeId (bc)))
4904 {
4905 if (ctype_isVoidPointer (t) || ctype_isUnknown (t))
4906 {
4907 vnoptgenerror
4908 (FLG_ABSTVOIDP,
4909 message ("Cast to underlying abstract type %t: %s",
4910 c, exprNode_unparse (ret)),
4911 e->loc);
4912 }
4913 else
4914 {
4915 voptgenerror
4916 (FLG_ABSTRACT,
4917 message ("Cast to underlying abstract type %t: %s",
4918 c, exprNode_unparse (ret)),
4919 e->loc);
4920 }
4921 }
4922
4923 if (ctype_isRealAbstract (bt)
4924 && !context_hasAccess (ctype_typeId (bt)))
4925 {
4926 if (ctype_isUnknown (c) || ctype_isVoidPointer (c))
4927 {
4928 vnoptgenerror
4929 (FLG_ABSTVOIDP,
4930 message ("Cast from underlying abstract type %t: %s",
4931 t, exprNode_unparse (ret)),
4932 e->loc);
4933 }
4934 else
4935 {
4936 voptgenerror
4937 (FLG_ABSTRACT,
4938 message ("Cast from underlying abstract type %t: %s",
4939 t, exprNode_unparse (ret)),
4940 e->loc);
4941 }
4942 }
4943 }
4944 }
4945 else
4946 {
4947 ctype bt = ctype_realType (ctype_getBaseType (t));
4948 ctype bc = ctype_realType (ctype_getBaseType (c));
4949
4950 if (ctype_isAbstract (bt) && !context_hasAccess (ctype_typeId (bt)))
4951 {
4952 if (ctype_match (c, t))
4953 {
4954 if (ctype_equal (c, t))
4955 {
4956 voptgenerror
4957 (FLG_TYPE,
4958 message ("Redundant cast involving abstract type %t: %s",
4959 bt, exprNode_unparse (ret)),
4960 e->loc);
4961 }
4962 }
4963 else
4964 {
4965 voptgenerror
4966 (FLG_ABSTRACT,
4967 message ("Cast from abstract type %t: %s",
4968 bt, exprNode_unparse (ret)),
4969 e->loc);
4970 }
4971 }
4972
4973 if (ctype_isAbstract (bc)
4974 && !context_hasAccess (ctype_typeId (bc)))
4975 {
4976 if (ctype_match (c, t))
4977 {
4978 ;
4979 }
4980 else
4981 {
28bf4b0b 4982 DPRINTF (("No access to: %s / %d",
4983 ctype_unparse (bc), ctype_typeId (bc)));
4984 DPRINTF (("Context %s %s",
4985 bool_unparse (context_inFunctionLike ()),
4986 context_unparse ()));
616915dd 4987 voptgenerror
4988 (FLG_ABSTRACT,
4989 message ("Cast to abstract type %t: %s", bc,
4990 exprNode_unparse (ret)),
4991 e->loc);
4992 }
4993 }
4994 }
4995
4996 if (ctype_isAbstract (c))
4997 {
4998 if (sRef_isExposed (e->sref) || sRef_isOnly (e->sref))
4999 {
5000 /* okay, cast exposed to abstract */
5001 sRef_clearExKindComplete (ret->sref, fileloc_undefined);
5002 }
5003 else
5004 {
5005 if (ctype_isVisiblySharable (t)
5006 && sRef_isExternallyVisible (e->sref)
5007 && !(ctype_isAbstract (t)
5008 && context_hasAccess (ctype_typeId (t))))
5009 {
5010 voptgenerror
5011 (FLG_CASTEXPOSE,
5012 message ("Cast to abstract type from externally visible "
5013 "mutable storage exposes rep of %s: %s",
5014 ctype_unparse (c),
5015 exprNode_unparse (e)),
5016 e->loc);
5017 }
5018 }
5019 }
5020
5021 return (ret);
5022}
5023
5024static bool
5025evaluationOrderUndefined (lltok op)
5026{
5027 int opid = lltok_getTok (op);
5028
5029 return (opid != AND_OP && opid != OR_OP);
5030}
5031
5032static bool checkIntegral (/*@notnull@*/ exprNode e1,
5033 /*@notnull@*/ exprNode e2,
5034 /*@notnull@*/ exprNode ret,
5035 lltok op)
5036{
5037 bool error = FALSE;
5038
5039 ctype te1 = exprNode_getType (e1);
5040 ctype te2 = exprNode_getType (e2);
5041
5042 ctype tr1 = ctype_realishType (te1);
5043 ctype tr2 = ctype_realishType (te2);
5044
5045 if (ctype_isForceRealInt (&tr1) && ctype_isForceRealInt (&tr2))
5046 {
5047 ;
5048 }
5049 else
5050 {
5051 if (context_msgStrictOps ())
5052 {
5053 if (!ctype_isInt (tr1) && !ctype_isInt (tr2))
5054 {
5055 if (ctype_sameName (te1, te2))
5056 {
5057 error = optgenerror
5058 (FLG_STRICTOPS,
5059 message ("Operands of %s are non-integer (%t): %s",
5060 lltok_unparse (op), te1,
5061 exprNode_unparse (ret)),
5062 e1->loc);
5063 }
5064 else
5065 {
5066 error = optgenerror
5067 (FLG_STRICTOPS,
5068 message ("Operands of %s are non-integers (%t, %t): %s",
5069 lltok_unparse (op), te1, te2,
5070 exprNode_unparse (ret)),
5071 e1->loc);
5072 }
5073 }
5074 else if (!ctype_isInt (tr1))
5075 {
5076 error = optgenerror
5077 (FLG_STRICTOPS,
5078 message ("Left operand of %s is non-integer (%t): %s",
5079 lltok_unparse (op), te1, exprNode_unparse (ret)),
5080 e1->loc);
5081 }
5082 else
5083 /* !ctype_isInt (te2) */
5084 {
5085 error = optgenerror
5086 (FLG_STRICTOPS,
5087 message ("Right operand of %s is non-integer (%t): %s",
5088 lltok_unparse (op), te2, exprNode_unparse (ret)),
5089 e2->loc);
5090 }
5091 }
5092 }
5093
5094 return !error;
5095}
5096
5097/*
5098** returns exprNode representing e1 op e2
5099**
5100** uses msg if there are errors
5101** can be used for both assignment ops and regular ops
5102**
5103** modifies e1
5104*/
5105
5106static /*@only@*/ /*@notnull@*/ exprNode
5107exprNode_makeOp (/*@keep@*/ exprNode e1, /*@keep@*/ exprNode e2,
5108 /*@keep@*/ lltok op)
5109{
5110 ctype te1, te2, tr1, tr2, tret;
5111 int opid = lltok_getTok (op);
5112 bool hasError = FALSE;
5113 exprNode ret;
5114
5115 if (exprNode_isError (e1))
5116 {
5117 ret = exprNode_createPartialNVCopy (e2);
5118 }
5119 else
5120 {
5121 ret = exprNode_createPartialNVCopy (e1);
5122 }
5123
5124 ret->val = multiVal_undefined;
5125 ret->kind = XPR_OP;
5126 ret->edata = exprData_makeOp (e1, e2, op);
5127
5128 if (exprNode_isError (e1) || exprNode_isError (e2))
5129 {
5130 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5131 || opid == EQ_OP || opid == NE_OP
5132 || opid == AND_OP || opid == OR_OP)
5133 {
5134 ret->typ = ctype_bool;
5135 }
5136
5137 if (exprNode_isDefined (e1))
5138 {
5139 exprNode_checkUse (ret, e1->sref, e1->loc);
5140 }
5141
5142 if (exprNode_isDefined (e2))
5143 {
5144 exprNode_mergeUSs (ret, e2);
5145 exprNode_checkUse (ret, e2->sref, e2->loc);
5146 }
5147
5148 return ret;
5149 }
5150
5151 tret = ctype_unknown;
5152 te1 = exprNode_getType (e1);
5153 DPRINTF (("te1 = %s / %s", exprNode_unparse (e1), ctype_unparse (te1)));
5154
5155 te2 = exprNode_getType (e2);
5156
5157 tr1 = ctype_realishType (te1);
5158 tr2 = ctype_realishType (te2);
5159
5160 if (opid == OR_OP)
5161 {
5162 ret->guards = guardSet_or (ret->guards, e2->guards);
5163 }
5164 else if (opid == AND_OP)
5165 {
5166 ret->guards = guardSet_and (ret->guards, e2->guards);
5167 }
5168 else
5169 {
5170 /* no guards */
5171 }
5172
5173 if (opid == EQ_OP || opid == NE_OP)
5174 {
5175 exprNode temp1 = e1, temp2 = e2;
5176
5177 /* could do NULL == x */
5178
5179 if (exprNode_isNullValue (e1) || exprNode_isUnknownConstant (e1))
5180 {
5181 temp1 = e2; temp2 = e1;
5182 }
5183
5184 if (exprNode_isNullValue (temp2) || exprNode_isUnknownConstant (temp2))
5185 {
5186 reflectNullTest (temp1, (opid == NE_OP));
5187 guardSet_free (ret->guards);
5188 ret->guards = guardSet_copy (temp1->guards);
5189 }
5190 }
5191
5192 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5193 || opid == EQ_OP || opid == NE_OP || opid == AND_OP || opid == OR_OP)
5194 {
5195 tret = ctype_bool;
5196 }
5197
5198 if (anyAbstract (tr1, tr2) &&
5199 (!((ctype_isRealBool (te1) || ctype_isRealBool (te2)) &&
5200 (opid == AND_OP || opid == OR_OP
5201 || opid == EQ_OP || opid == NE_OP))))
5202 {
5203 abstractOpError (tr1, tr2, op, e1, e2, e1->loc, e2->loc);
5204 }
5205 else if (ctype_isUnknown (te1) || ctype_isUnknown (te2))
5206 {
5207 /* unknown types, no comparisons possible */
5208 }
5209 else
5210 {
5211 switch (opid)
5212 {
5213 case TMULT: /* multiplication and division: */
5214 case TDIV: /* */
5215 case MUL_ASSIGN: /* numeric, numeric -> numeric */
5216 case DIV_ASSIGN: /* */
5217
5218 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5219 break;
5220
5221 case TPLUS: /* addition and subtraction: */
5222 case TMINUS: /* pointer, int -> pointer */
5223 case SUB_ASSIGN: /* int, pointer -> pointer */
5224 case ADD_ASSIGN: /* numeric, numeric -> numeric */
5225
5226 tr1 = ctype_fixArrayPtr (tr1);
5227
5228 if ((ctype_isRealPointer (tr1) && !exprNode_isNullValue (e1))
5229 && (!ctype_isRealPointer (tr2) && ctype_isRealInt (tr2)))
5230 {
5231 /* pointer + int */
5232
5233 if (context_msgPointerArith ())
5234 {
5235 voptgenerror
5236 (FLG_POINTERARITH,
5237 message ("Pointer arithmetic (%t, %t): %s",
5238 te1, te2, exprNode_unparse (ret)),
5239 e1->loc);
5240 }
5241
ccf0a4a8 5242 /*
5243 ** Swap terms so e1 is always the pointer
5244 */
5245
5246 if (ctype_isRealPointer (tr1))
5247 {
5248 ;
5249 }
5250 else
5251 {
5252 exprNode_swap (e1, e2);
5253 }
5254
5255
616915dd 5256 if (sRef_possiblyNull (e1->sref)
5257 && !usymtab_isGuarded (e1->sref))
5258 {
5259 voptgenerror
5260 (FLG_NULLPOINTERARITH,
5261 message ("Pointer arithmetic involving possibly "
5262 "null pointer %s: %s",
5263 exprNode_unparse (e1),
5264 exprNode_unparse (ret)),
5265 e1->loc);
5266 }
5267
5268 ret->sref = sRef_copy (e1->sref);
5269
ccf0a4a8 5270 /* start modifications */
5271 /* added by Seejo on 4/16/2000 */
616915dd 5272
ccf0a4a8 5273 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5274 status */
5275 if ((sRef_isPossiblyNullTerminated (e1->sref)) || (sRef_isNullTerminated(e1->sref))) {
616915dd 5276 //if (sRef_isKnown (e->sref)) {
5277 //ret->sref = sRef_makeAddress (e->sref);
5278 //}
ccf0a4a8 5279
5280 int val;
5281 /*drl 1-4-2001
5282 added ugly fixed to stop
5283 program from crashing on point + int +int
5284 one day I'll fix this or ask Seejo wtf the codes supposed to do. */
5285
5286 if (!multiVal_isInt (e2->val) )
5287 break;
5288 /*end drl*/
5289
5290 val = (int) multiVal_forceInt (e2->val);
5291
5292 /* Operator : + or += */
5293 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5294 if (sRef_getSize(e1->sref) >= val) {/* Incrementing the pointer by
5295 val should not result in a
5296 size < 0 (size = 0 is ok !) */
5297
5298 sRef_setSize (ret->sref, sRef_getSize(e1->sref) - val);
5299
5300 if (sRef_getLen(e1->sref) == val) { /* i.e. the character at posn val is \0 */
5301 sRef_setNotNullTerminatedState(ret->sref);
5302 sRef_resetLen (ret->sref);
5303 } else {
5304 sRef_setNullTerminatedState(ret->sref);
5305 sRef_setLen (ret->sref, sRef_getLen(e1->sref) - val);
5306 }
5307 }
5308 }
5309
5310 /* Operator : - or -= */
5311 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5312 if (sRef_getSize(e1->sref) >= 0) {
5313 sRef_setSize (ret->sref, sRef_getSize(e1->sref) + val);
5314 sRef_setLen (ret->sref, sRef_getLen(e1->sref) + val);
5315 }
5316 }
5317 }
616915dd 5318
ccf0a4a8 5319 /* end modifications */
616915dd 5320
5321 sRef_setNullError (ret->sref);
5322
5323 /*
5324 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5325 ** since is points to storage that should not be deallocated
5326 ** through this pointer.
5327 */
5328
5329 if (sRef_isOnly (ret->sref)
5330 || sRef_isFresh (ret->sref))
5331 {
5332 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5333 }
5334
5335 tret = e1->typ;
5336 }
5337 else if ((!ctype_isRealPointer(tr1) && ctype_isRealInt (tr1))
5338 && (ctype_isRealPointer (tr2) && !exprNode_isNullValue (e2)))
5339 {
5340 if (context_msgPointerArith ())
5341 {
5342 voptgenerror
5343 (FLG_POINTERARITH,
5344 message ("Pointer arithmetic (%t, %t): %s",
5345 te1, te2, exprNode_unparse (ret)),
5346 e1->loc);
5347 }
5348
5349 if (sRef_possiblyNull (e1->sref)
5350 && !usymtab_isGuarded (e1->sref))
5351 {
5352 voptgenerror
5353 (FLG_NULLPOINTERARITH,
5354 message ("Pointer arithmetic involving possibly "
5355 "null pointer %s: %s",
5356 exprNode_unparse (e2),
5357 exprNode_unparse (ret)),
5358 e2->loc);
5359 }
5360
5361 ret->sref = sRef_copy (e2->sref);
5362
5363 /* start modifications */
5364 /* added by Seejo on 4/16/2000 */
5365
5366 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5367 status */
5368
5369 if ((sRef_isPossiblyNullTerminated (e2->sref)) || (sRef_isNullTerminated(e2->sref))) {
5370 //if (sRef_isKnown (e->sref)) {
5371 //ret->sref = sRef_makeAddress (e->sref);
5372 //}
5373
5374 int val = (int) multiVal_forceInt (e1->val);
5375
5376 /* Operator : + or += */
5377 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5378 if (sRef_getSize(e2->sref) >= val) {/* Incrementing the pointer by
5379 val should not result in a
5380 size < 0 (size = 0 is ok !) */
5381
5382 sRef_setSize (ret->sref, sRef_getSize(e2->sref) - val);
5383
5384 if (sRef_getLen(e2->sref) == val) { /* i.e. the character at posn val is \0 */
5385 sRef_setNotNullTerminatedState(ret->sref);
5386 sRef_resetLen (ret->sref);
5387 } else {
5388 sRef_setNullTerminatedState(ret->sref);
5389 sRef_setLen (ret->sref, sRef_getLen(e2->sref) - val);
5390 }
5391 }
5392 }
5393
5394 /* Operator : - or -= */
5395 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5396 if (sRef_getSize(e2->sref) >= 0) {
5397 sRef_setSize (ret->sref, sRef_getSize(e2->sref) + val);
5398 sRef_setLen (ret->sref, sRef_getLen(e2->sref) + val);
5399 }
5400 }
5401 }
5402
5403 /* end modifications */
5404
5405 sRef_setNullError (ret->sref);
5406
5407 /*
5408 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5409 ** since is points to storage that should not be deallocated
5410 ** through this pointer.
5411 */
5412
5413 if (sRef_isOnly (ret->sref)
5414 || sRef_isFresh (ret->sref)) {
5415 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5416 }
5417
5418 tret = e2->typ;
5419 ret->sref = e2->sref;
5420 }
5421 else
5422 {
5423 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5424 }
5425
5426 break;
5427
5428 case LEFT_ASSIGN: /* Shifts: should be unsigned values */
5429 case RIGHT_ASSIGN:
5430 case LEFT_OP:
5431 case RIGHT_OP:
5432 case TAMPERSAND: /* bitwise & */
5433 case AND_ASSIGN:
5434 case TCIRC: /* ^ (XOR) */
5435 case TBAR:
5436 case XOR_ASSIGN:
5437 case OR_ASSIGN:
5438 {
5439 bool reported = FALSE;
5440 flagcode code = FLG_BITWISEOPS;
5441
5442 if (opid == LEFT_OP || opid == LEFT_ASSIGN
5443 || opid == RIGHT_OP || opid == RIGHT_ASSIGN) {
5444 code = FLG_SHIFTSIGNED;
5445 }
5446
5447 if (!ctype_isUnsigned (tr1))
5448 {
5449 if (exprNode_isNonNegative (e1)) {
5450 ;
5451 } else {
5452 reported = optgenerror
5453 (code,
5454 message ("Left operand of %s is not unsigned value (%t): %s",
5455 lltok_unparse (op), te1,
5456 exprNode_unparse (ret)),
5457 e1->loc);
5458
5459 if (reported) {
5460 te1 = ctype_uint;
5461 }
5462 }
5463 }
5464 else
5465 {
5466 /* right need not be signed for shifts */
5467 if (code != FLG_SHIFTSIGNED
5468 && !ctype_isUnsigned (tr2))
5469 {
5470 if (!exprNode_isNonNegative (e2)) {
5471 reported = optgenerror
5472 (code,
5473 message ("Right operand of %s is not unsigned value (%t): %s",
5474 lltok_unparse (op), te2,
5475 exprNode_unparse (ret)),
5476 e2->loc);
5477 }
5478 }
5479 }
5480
5481 if (!reported)
5482 {
5483 if (!checkIntegral (e1, e2, ret, op)) {
5484 te1 = ctype_unknown;
5485 }
5486 }
5487
5488 DPRINTF (("Set: %s", ctype_unparse (te1)));
5489
5490 /*
5491 ** tret is the widest type of te1 and te2
5492 */
5493
5494 tret = ctype_widest (te1, te2);
5495 break;
5496 }
5497 case MOD_ASSIGN:
5498 case TPERCENT:
5499 if (checkIntegral (e1, e2, ret, op)) {
5500 tret = te1;
5501 } else {
5502 tret = ctype_unknown;
5503 }
5504 break;
5505 case EQ_OP:
5506 case NE_OP:
5507 case TLT: /* comparisons */
5508 case TGT: /* numeric, numeric -> bool */
5509 if ((ctype_isReal (tr1) && !ctype_isInt (tr1))
5510 || (ctype_isReal (tr2) && !ctype_isInt (tr2)))
5511 {
5512 ctype rtype = tr1;
5513 bool fepsilon = FALSE;
5514
5515 if (!ctype_isReal (rtype) || ctype_isInt (rtype))
5516 {
5517 rtype = tr2;
5518 }
5519
5520 if (opid == TLT || opid == TGT)
5521 {
5522 uentry ue1 = exprNode_getUentry (e1);
5523 uentry ue2 = exprNode_getUentry (e2);
5524
5525 /*
5526 ** FLT_EPSILON, etc. really is a variable, not
5527 ** a constant.
5528 */
5529
5530 if (uentry_isVariable (ue1))
5531 {
5532 cstring uname = uentry_rawName (ue1);
5533
5534 if (cstring_equalLit (uname, "FLT_EPSILON")
5535 || cstring_equalLit (uname, "DBL_EPSILON")
5536 || cstring_equalLit (uname, "LDBL_EPSILON"))
5537 {
5538 fepsilon = TRUE;
5539 }
5540 }
5541
5542 if (uentry_isVariable (ue2))
5543 {
5544 cstring uname = uentry_rawName (ue2);
5545
5546 if (cstring_equalLit (uname, "FLT_EPSILON")
5547 || cstring_equalLit (uname, "DBL_EPSILON")
5548 || cstring_equalLit (uname, "LDBL_EPSILON"))
5549 {
5550 fepsilon = TRUE;
5551 }
5552 }
5553 }
5554
5555 if (fepsilon)
5556 {
5557 ; /* Don't complain. */
5558 }
5559 else
5560 {
5561 voptgenerror
5562 (FLG_REALCOMPARE,
5563 message ("Dangerous comparison involving %s types: %s",
5564 ctype_unparse (rtype),
5565 exprNode_unparse (ret)),
5566 ret->loc);
5567 }
5568 }
5569 /*@fallthrough@*/
5570 case LE_OP:
5571 case GE_OP:
5572
5573 /*
5574 ** Types should match.
5575 */
5576
5577 if (!exprNode_matchTypes (e1, e2))
5578 {
5579 hasError = gentypeerror
5580 (te1, e1, te2, e2,
5581 message ("Operands of %s have incompatible types (%t, %t): %s",
5582 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5583 e1->loc);
5584
5585 }
5586
5587 if (hasError
5588 || (ctype_isForceRealNumeric (&tr1)
5589 && ctype_isForceRealNumeric (&tr2)) ||
5590 (ctype_isRealPointer (tr1) && ctype_isRealPointer (tr2)))
5591 {
5592 ; /* okay */
5593 }
5594 else
5595 {
5596 if ((ctype_isRealNumeric (tr1) && ctype_isRealPointer (tr2)) ||
5597 (ctype_isRealPointer (tr1) && ctype_isRealNumeric (tr2)))
5598 {
5599 voptgenerror
5600 (FLG_PTRNUMCOMPARE,
5601 message ("Comparison of pointer and numeric (%t, %t): %s",
5602 te1, te2, exprNode_unparse (ret)),
5603 e1->loc);
5604 }
5605 else
5606 {
5607 (void) checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5608 }
5609 tret = ctype_bool;
5610 }
5611
5612 /* EQ_OP should NOT be used with booleans (unless one is FALSE) */
5613
5614 if ((opid == EQ_OP || opid == NE_OP) &&
5615 ctype_isDirectBool (tr1) && ctype_isDirectBool (tr2))
5616 {
5617 /*
5618 ** is one a variable?
5619 */
5620
5621 if (uentry_isVariable (exprNode_getUentry (e1))
5622 || uentry_isVariable (exprNode_getUentry (e2)))
5623 {
5624 /*
5625 ** comparisons with FALSE are okay
5626 */
5627
5628 if (exprNode_isFalseConstant (e1)
5629 || exprNode_isFalseConstant (e2))
5630 {
5631 ;
5632 }
5633 else
5634 {
5635 voptgenerror
5636 (FLG_BOOLCOMPARE,
5637 message
5638 ("Use of %q with %s variables (risks inconsistency because "
5639 "of multiple true values): %s",
5640 cstring_makeLiteral ((opid == EQ_OP) ? "==" : "!="),
5641 context_printBoolName (), exprNode_unparse (ret)),
5642 e1->loc);
5643 }
5644 }
5645 }
5646 break;
5647
5648 case AND_OP: /* bool, bool -> bool */
5649 case OR_OP:
5650
5651 if (ctype_isForceRealBool (&tr1) && ctype_isForceRealBool (&tr2))
5652 {
5653 ;
5654 }
5655 else
5656 {
5657 if (context_maybeSet (FLG_BOOLOPS))
5658 {
5659 if (!ctype_isRealBool (te1) && !ctype_isRealBool (te2))
5660 {
5661 if (ctype_sameName (te1, te2))
5662 {
5663 voptgenerror
5664 (FLG_BOOLOPS,
5665 message ("Operands of %s are non-boolean (%t): %s",
5666 lltok_unparse (op), te1,
5667 exprNode_unparse (ret)),
5668 e1->loc);
5669 }
5670 else
5671 {
5672 voptgenerror
5673 (FLG_BOOLOPS,
5674 message
5675 ("Operands of %s are non-booleans (%t, %t): %s",
5676 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5677 e1->loc);
5678 }
5679 }
5680 else if (!ctype_isRealBool (te1))
5681 {
5682 voptgenerror
5683 (FLG_BOOLOPS,
5684 message ("Left operand of %s is non-boolean (%t): %s",
5685 lltok_unparse (op), te1, exprNode_unparse (ret)),
5686 e1->loc);
5687 }
5688 else if (!ctype_isRealBool (te2))
5689 {
5690 voptgenerror
5691 (FLG_BOOLOPS,
5692 message ("Right operand of %s is non-boolean (%t): %s",
5693 lltok_unparse (op), te2, exprNode_unparse (ret)),
5694 e2->loc);
5695 }
5696 else
5697 {
5698 ;
5699 }
5700 }
5701 tret = ctype_bool;
5702 }
5703 break;
5704 default: {
5705 llfatalbug
5706 (cstring_makeLiteral
28bf4b0b 5707 ("There has been a problem in the parser. This is believed to result "
5708 "from a problem with bison v. 1.25. Please try rebuidling LCLint "
5709 "using the pre-compiled grammar files by commenting out the "
5710 "BISON= line in the top-level Makefile."));
616915dd 5711 }
5712 }
5713 }
5714
5715 DPRINTF (("Return type: %s", ctype_unparse (tret)));
5716 ret->typ = tret;
5717
5718 exprNode_checkUse (ret, e1->sref, e1->loc);
5719 exprNode_mergeUSs (ret, e2);
5720 exprNode_checkUse (ret, e2->sref, e2->loc);
5721
5722 return ret;
5723}
5724
5725/*@only@*/ exprNode
5726exprNode_op (/*@only@*/ exprNode e1, /*@keep@*/ exprNode e2,
5727 /*@only@*/ lltok op)
5728{
5729 exprNode ret;
5730
5731 checkMacroParen (e1);
5732 checkMacroParen (e2);
5733
5734 if (evaluationOrderUndefined (op) && context_maybeSet (FLG_EVALORDER))
5735 {
5736 checkExpressionDefined (e1, e2, op);
5737 }
5738
5739 ret = exprNode_makeOp (e1, e2, op);
5740 return (ret);
5741}
5742
5743static
5744void exprNode_checkAssignMod (exprNode e1, exprNode ret)
5745{
5746 /*
5747 ** This is somewhat bogus!
5748 **
5749 ** Assigning to a nested observer in a non-observer datatype
5750 ** should not produce an error.
5751 */
5752
5753 sRef ref = exprNode_getSref (e1);
5754
5755 DPRINTF (("Check assign mod: %s",
5756 sRef_unparseFull (ref)));
5757
5758 if (sRef_isObserver (ref)
28bf4b0b 5759 || ((sRef_isFileStatic (ref) || sRef_isFileOrGlobalScope (ref))
616915dd 5760 && ctype_isArray (ctype_realType (sRef_getType (ref)))))
5761 {
5762 sRef base = sRef_getBase (ref);
5763
5764 if (sRef_isValid (base) && sRef_isObserver (base))
5765 {
5766 exprNode_checkModify (e1, ret);
5767 }
5768 else
5769 {
5770 exprNode_checkModifyVal (e1, ret);
5771 }
5772 }
5773 else
5774 {
5775 exprNode_checkModify (e1, ret);
5776 }
5777}
5778
5779exprNode
5780exprNode_assign (/*@only@*/ exprNode e1,
5781 /*@only@*/ exprNode e2, /*@only@*/ lltok op)
5782{
5783 bool isalloc = FALSE;
5784 bool isjustalloc = FALSE;
5785 exprNode ret;
5786
5787 DPRINTF (("%s [%s] <- %s [%s]",
5788 exprNode_unparse (e1),
5789 ctype_unparse (e1->typ),
5790 exprNode_unparse (e2),
5791 ctype_unparse (e2->typ)));
5792
5793 if (lltok_getTok (op) != TASSIGN)
5794 {
5795 ret = exprNode_makeOp (e1, e2, op);
5796 }
5797 else
5798 {
5799 ret = exprNode_createPartialCopy (e1);
5800 ret->kind = XPR_ASSIGN;
5801 ret->edata = exprData_makeOp (e1, e2, op);
5802
5803 if (!exprNode_isError (e2))
5804 {
5805 ret->sets = sRefSet_union (ret->sets, e2->sets);
5806 ret->msets = sRefSet_union (ret->msets, e2->msets);
5807 ret->uses = sRefSet_union (ret->uses, e2->uses);
5808 }
5809 }
5810
5811 checkExpressionDefined (e1, e2, op);
5812
5813 if (exprNode_isError (e1))
5814 {
5815 if (!exprNode_isError (e2))
5816 {
5817 ret->loc = fileloc_update (ret->loc, e2->loc);
5818 }
5819 else
5820 {
5821 ret->loc = fileloc_update (ret->loc, g_currentloc);
5822 }
5823 }
5824
5825 if (!exprNode_isError (e2))
5826 {
5827 checkMacroParen (e2);
5828 }
5829
5830 if (exprNode_isDefined (e1))
5831 {
5832 if (sRef_isMacroParamRef (e1->sref))
5833 {
5834 if (context_inIterDef ())
5835 {
5836 uentry ue = sRef_getUentry (e1->sref);
5837
5838 if (uentry_isYield (ue))
5839 {
5840 ;
5841 }
5842 else
5843 {
5844 if (fileloc_isDefined (e1->loc))
5845 {
5846 voptgenerror
5847 (FLG_MACROPARAMS,
5848 message ("Assignment to non-yield iter parameter: %q",
5849 sRef_unparse (e1->sref)),
5850 e1->loc);
5851 }
5852 else
5853 {
5854 voptgenerror
5855 (FLG_MACROPARAMS,
5856 message ("Assignment to non-yield iter parameter: %q",
5857 sRef_unparse (e1->sref)),
5858 g_currentloc);
5859 }
5860 }
5861 }
5862 else
5863 {
5864 if (fileloc_isDefined (e1->loc))
5865 {
5866 voptgenerror
5867 (FLG_MACROASSIGN,
5868 message ("Assignment to macro parameter: %q",
5869 sRef_unparse (e1->sref)),
5870 e1->loc);
5871 }
5872 else
5873 {
5874 voptgenerror
5875 (FLG_MACROASSIGN,
5876 message ("Assignment to macro parameter: %q",
5877 sRef_unparse (e1->sref)),
5878 g_currentloc);
5879 }
ccf0a4a8 5880
5881 exprNode_checkAssignMod (e1, ret); /* evans 2001-07-22 */
616915dd 5882 }
5883 }
5884 else
5885 {
5886 exprNode_checkAssignMod (e1, ret);
5887 }
5888
5889 if (exprNode_isDefined (e2))
5890 {
5891 if (lltok_getTok (op) == TASSIGN)
5892 {
5893 ctype te1 = exprNode_getType (e1);
5894 ctype te2 = exprNode_getType (e2);
5895
5896 if (!ctype_forceMatch (te1, te2))
5897 {
5898 if (exprNode_matchLiteral (te1, e2))
5899 {
5900 ;
5901 }
5902 else
5903 {
5904 (void) gentypeerror
5905 (te2, e2, te1, e1,
5906 message ("Assignment of %t to %t: %s %s %s",
5907 te2, te1, exprNode_unparse (e1),
5908 lltok_unparse (op),
5909 exprNode_unparse (e2)),
5910 e1->loc);
5911 }
5912 }
5913 }
5914
5915 exprNode_mergeUSs (ret, e2);
5916 exprNode_checkUse (ret, e2->sref, e2->loc);
5917
5918 doAssign (e1, e2, FALSE);
5919 ret->sref = e1->sref;
5920 }
5921 else
5922 {
5923 if (exprNode_isDefined (e2))
5924 {
5925 exprNode_mergeUSs (ret, e2);
5926 exprNode_checkUse (ret, e2->sref, e2->loc);
5927 }
5928 }
5929
5930 if (sRef_isPointer (e1->sref) && !sRef_isMacroParamRef (e1->sref))
5931 {
5932 exprNode_checkUse (ret, sRef_getBase (e1->sref), e1->loc);
5933 }
5934
5935 isjustalloc = sRef_isJustAllocated (e1->sref);
5936 isalloc = sRef_isAllocated (e1->sref);
5937
5938 if (sRef_isField (e1->sref))
5939 {
5940 sRef root = sRef_getRootBase (sRef_getBase (e1->sref));
5941
5942 if (!sRef_isAllocated (root) && !sRef_isMacroParamRef (root))
5943 {
5944 exprNode_checkUse (ret, root, e1->loc);
5945 }
5946
5947 }
5948
5949 /*
5950 ** be careful! this defines e1->sref.
5951 */
ccf0a4a8 5952
5953 /* evans 2001-07-22: removed if (!sRef_isMacroParamRef (e1->sref)) */
5954
5955 exprNode_checkSet (ret, e1->sref);
616915dd 5956
5957 if (isjustalloc)
5958 {
5959 sRef_setAllocatedComplete (e1->sref, exprNode_isDefined (e2)
5960 ? e2->loc : e1->loc);
5961 }
5962 else
5963 {
5964 if (isalloc)
5965 {
5966 sRef_setAllocatedShallowComplete (e1->sref, exprNode_loc (e2));
5967 }
5968 }
5969 }
5970
5971 return ret;
5972}
5973
5974exprNode
5975exprNode_cond (/*@keep@*/ exprNode pred, /*@keep@*/ exprNode ifclause,
5976 /*@keep@*/ exprNode elseclause)
5977{
5978 exprNode ret;
5979
5980 if (!exprNode_isError (pred))
5981 {
5982 ret = exprNode_createPartialCopy (pred);
5983 checkMacroParen (pred);
5984 exprNode_checkPred (cstring_makeLiteralTemp ("conditional"), pred);
5985
5986 if (!exprNode_isError (ifclause))
5987 {
5988 checkMacroParen (ifclause); /* update macro counts! */
5989
5990 if (!exprNode_isError (elseclause))
5991 {
5992 checkMacroParen (elseclause);
5993
5994 if (!exprNode_matchTypes (ifclause, elseclause))
5995 {
5996 if (gentypeerror
5997 (exprNode_getType (ifclause),
5998 ifclause,
5999 exprNode_getType (elseclause),
6000 elseclause,
6001 message ("Conditional clauses are not of same type: "
6002 "%s (%t), %s (%t)",
6003 exprNode_unparse (ifclause),
6004 exprNode_getType (ifclause),
6005 exprNode_unparse (elseclause),
6006 exprNode_getType (elseclause)),
6007 ifclause->loc))
6008 {
6009 ret->sref = sRef_undefined;
6010 ret->typ = ctype_unknown;
6011 }
6012 }
6013 else
6014 {
6015 /* for now...should merge the states */
6016 ret->sref = ifclause->sref;
6017 ret->typ = ifclause->typ;
6018
6019 if (exprNode_isNullValue (ifclause))
6020 {
6021 ret->typ = elseclause->typ;
6022 }
6023 }
6024
6025 exprNode_checkUse (ret, pred->sref, pred->loc);
6026 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6027 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6028
6029 exprNode_mergeCondUSs (ret, ifclause, elseclause);
6030
6031 }
6032 else
6033 {
6034 ret->typ = ifclause->typ;
6035
6036 exprNode_checkUse (pred, pred->sref, pred->loc);
6037 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6038
6039 exprNode_mergeCondUSs (ret, ifclause, exprNode_undefined);
6040 }
6041 }
6042 else
6043 {
6044 if (!exprNode_isError (elseclause))
6045 {
6046 ret->typ = elseclause->typ;
6047
6048 exprNode_checkUse (pred, pred->sref, pred->loc);
6049 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6050
6051 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6052 }
6053 }
6054 }
6055 else /* pred is error */
6056 {
6057 if (!exprNode_isError (ifclause))
6058 {
6059 ret = exprNode_createSemiCopy (ifclause);
6060
6061 checkMacroParen (ifclause); /* update macro counts! */
6062
6063 if (!exprNode_isError (elseclause))
6064 {
6065 checkMacroParen (elseclause);
6066
6067 ret->typ = ifclause->typ;
6068
6069 if (!ctype_forceMatch (ifclause->typ, elseclause->typ))
6070 {
6071 if (gentypeerror
6072 (exprNode_getType (ifclause),
6073 ifclause,
6074 exprNode_getType (elseclause),
6075 elseclause,
6076 message ("Conditional clauses are not of same type: "
6077 "%s (%t), %s (%t)",
6078 exprNode_unparse (ifclause),
6079 exprNode_getType (ifclause),
6080 exprNode_unparse (elseclause),
6081 exprNode_getType (elseclause)),
6082 ifclause->loc))
6083 {
6084 ret->typ = ctype_unknown;
6085 }
6086 }
6087
6088 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6089 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6090
6091 exprNode_mergeCondUSs (ret, ifclause, elseclause);
6092 }
6093 }
6094 else if (!exprNode_isError (elseclause)) /* pred, if errors */
6095 {
6096 ret = exprNode_createSemiCopy (ifclause);
6097
6098 ret->typ = elseclause->typ;
6099 checkMacroParen (elseclause);
6100
6101 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6102 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6103 }
6104 else /* all errors! */
6105 {
6106 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
6107 }
6108 }
6109
6110 ret->kind = XPR_COND;
6111 ret->edata = exprData_makeCond (pred, ifclause, elseclause);
6112
6113 if (exprNode_isDefined (ifclause) && exprNode_isDefined (elseclause))
6114 {
6115 exprNode_combineControl (ret, ifclause, elseclause);
6116 }
6117
6118 return (ret);
6119}
6120
6121exprNode
6122exprNode_vaArg (/*@only@*/ lltok tok, /*@only@*/ exprNode arg, /*@only@*/ qtype qt)
6123{
6124 ctype totype = qtype_getType (qt);
6125 exprNode ret =
6126 exprNode_createPartialLocCopy (arg, fileloc_copy (lltok_getLoc (tok)));
6127 ctype targ;
6128
6129 /*
6130 ** check use of va_arg : <valist>, type -> type
6131 */
6132
6133 if (exprNode_isError (arg))
6134 {
6135 }
6136 else
6137 {
6138 targ = exprNode_getType (arg);
6139
6140 /*
6141 ** arg should have be a pointer
6142 */
6143
6144 if (!ctype_isUA (targ) ||
6145 (!usymId_equal (ctype_typeId (targ),
6146 usymtab_getTypeId (cstring_makeLiteralTemp ("va_list")))))
6147 {
6148 voptgenerror
6149 (FLG_TYPE,
6150 message ("First argument to va_arg is not a va_list (type %t): %s",
6151 targ, exprNode_unparse (arg)),
6152 arg->loc);
6153 }
6154
6155 exprNode_checkSet (ret, arg->sref);
6156 }
6157
6158 /*
6159 ** return type is totype
6160 */
6161
6162 ret->typ = totype;
6163 ret->kind = XPR_VAARG;
6164 ret->edata = exprData_makeCast (tok, arg, qt);
6165
6166 return (ret);
6167}
6168
6169exprNode exprNode_labelMarker (/*@only@*/ cstring label)
6170{
6171 exprNode ret = exprNode_createPlain (ctype_undefined);
6172 ret->kind = XPR_LABEL;
6173 ret->edata = exprData_makeLiteral (label);
6174 ret->isJumpPoint = TRUE;
6175
6176 return (ret); /* for now, ignore label */
6177}
6178
6179exprNode exprNode_notReached (/*@returned@*/ exprNode stmt)
6180{
6181 if (exprNode_isDefined (stmt))
6182 {
6183 stmt->isJumpPoint = TRUE;
6184
6185 /* This prevent stray no return path errors, etc. */
6186 stmt->exitCode = XK_MUSTEXIT;
6187 }
6188
6189 return (stmt);
6190}
6191
6192bool exprNode_isDefaultMarker (exprNode e)
6193{
6194 if (exprNode_isDefined (e))
6195 {
6196 return (e->kind == XPR_DEFAULT || e->kind == XPR_FTDEFAULT);
6197 }
6198
6199 return FALSE;
6200}
6201
6202bool exprNode_isCaseMarker (exprNode e)
6203{
6204 if (exprNode_isDefined (e))
6205 {
6206 return (e->kind == XPR_FTCASE || e->kind == XPR_CASE);
6207 }
6208
6209 return FALSE;
6210}
6211
6212bool exprNode_isLabelMarker (exprNode e)
6213{
6214 if (exprNode_isDefined (e))
6215 {
6216 return (e->kind == XPR_LABEL);
6217 }
6218
6219 return FALSE;
6220}
6221
6222exprNode exprNode_caseMarker (/*@only@*/ exprNode test, bool fallThrough)
6223{
6224 exprNode ret = exprNode_createPartialCopy (test);
6225
6226 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6227
6228 if (exprNode_isError (test)) {
6229 return ret;
6230 }
6231
6232 exprNode_checkUse (ret, test->sref, test->loc);
6233
6234 usymtab_setExitCode (ret->exitCode);
6235
6236 if (ret->mustBreak)
6237 {
6238 usymtab_setMustBreak ();
6239 }
6240
6241 ret->edata = exprData_makeSingle (test);
6242 ret->isJumpPoint = TRUE;
6243
6244 return ret;
6245}
6246
6247# if 0
6248exprNode exprNode_caseStatement (/*@only@*/ exprNode test, /*@only@*/ exprNode stmt, bool fallThrough)
6249{
6250 exprNode ret = exprNode_createPartialCopy (test);
6251
6252 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6253 ret->edata = exprData_makePair (test, stmt);
6254 ret->isJumpPoint = TRUE;
6255
6256 if (exprNode_isError (test))
6257 {
6258 return ret;
6259 }
6260
6261 exprNode_checkUse (ret, test->sref, test->loc);
6262
6263 if (exprNode_isError (stmt))
6264 {
6265 return ret;
6266 }
6267
6268 exprNode_mergeUSs (ret, stmt);
6269
6270 ret->exitCode = stmt->exitCode;
6271 ret->mustBreak = stmt->mustBreak;
6272 ret->canBreak = stmt->canBreak;
6273
6274 usymtab_setExitCode (ret->exitCode);
6275
6276 if (ret->mustBreak)
6277 {
6278 usymtab_setMustBreak ();
6279 }
6280
6281 return ret;
6282}
6283# endif
6284
6285/*@notnull@*/ /*@only@*/ exprNode
6286exprNode_defaultMarker (/*@only@*/ lltok def, bool fallThrough)
6287{
6288 exprNode ret = exprNode_createTok (def);
6289
6290 ret->isJumpPoint = TRUE;
6291 ret->kind = fallThrough ? XPR_FTDEFAULT : XPR_DEFAULT;
6292 return (ret);
6293}
6294
6295bool
6296exprNode_mayEscape (exprNode e)
6297{
6298 if (exprNode_isDefined (e))
6299 {
6300 return exitkind_couldEscape (e->exitCode);
6301 }
6302 return FALSE;
6303}
6304
6305static bool
6306exprNode_mustBreak (exprNode e)
6307{
6308 if (exprNode_isDefined (e))
6309 {
6310 return e->mustBreak;
6311 }
6312 return FALSE;
6313}
6314
6315bool
6316exprNode_mustEscape (exprNode e)
6317{
6318 if (exprNode_isDefined (e))
6319 {
6320 return exitkind_mustEscape (e->exitCode) || exprNode_mustBreak (e);
6321 }
6322
6323 return FALSE;
6324}
6325
6326bool
6327exprNode_errorEscape (exprNode e)
6328{
6329 if (exprNode_isDefined (e))
6330 {
6331 return exitkind_isError (e->exitCode);
6332 }
6333
6334 return FALSE;
6335}
6336
6337exprNode exprNode_concat (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
6338{
6339 exprNode ret = exprNode_createPartialCopy (e1);
6340
28bf4b0b 6341 DPRINTF (("Concat: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6342
616915dd 6343 ret->edata = exprData_makePair (e1, e2);
6344 ret->kind = XPR_STMTLIST;
6345
6346 if (exprNode_isDefined (e1))
6347 {
6348 ret->isJumpPoint = e1->isJumpPoint;
6349 ret->canBreak = e1->canBreak;
6350 }
6351 else
6352 {
6353 if (exprNode_isDefined (e2))
6354 {
6355 ret->loc = fileloc_update (ret->loc, e2->loc);
6356 }
6357 }
6358
6359 if (exprNode_isDefined (e2))
6360 {
6361 ret->exitCode = e2->exitCode;
6362 ret->mustBreak = e2->mustBreak;
6363 if (e2->canBreak) ret->canBreak = TRUE;
6364 }
6365
6366 /*
6367 ** if e1 must return, then e2 is unreachable!
6368 */
6369
6370 if (exprNode_isDefined (e1) && exprNode_isDefined (e2))
6371 {
6372 if ((exprNode_mustEscape (e1) || exprNode_mustBreak (e1))
6373 && !(e2->isJumpPoint))
6374 {
6375 if (context_getFlag (FLG_UNREACHABLE))
6376 {
6377 exprNode nr = e2;
6378
6379 if (e2->kind == XPR_STMT)
6380 {
6381 nr = exprData_getUopNode (e2->edata);
6382 }
6383
6384 if ((nr->kind == XPR_TOK
6385 && lltok_isSemi (exprData_getTok (nr->edata))))
6386 {
6387 /* okay to have unreachable ";" */
6388 ret->exitCode = XK_MUSTEXIT;
6389 ret->canBreak = TRUE;
6390 }
6391 else
6392 {
6393 if (optgenerror (FLG_UNREACHABLE,
6394 message ("Unreachable code: %s",
6395 exprNode_unparseFirst (nr)),
6396 exprNode_loc (nr)))
6397 {
6398 ret->isJumpPoint = TRUE;
6399 ret->mustBreak = FALSE;
6400 ret->exitCode = XK_ERROR;
6401 DPRINTF (("Jump point: %s", exprNode_unparse (ret)));
6402 }
6403 else
6404 {
6405 ret->exitCode = XK_MUSTEXIT;
6406 ret->canBreak = TRUE;
6407 }
6408
6409 }
6410 }
6411 }
6412 else
6413 {
6414 if ((e2->kind == XPR_CASE || e2->kind == XPR_DEFAULT))
6415 {
6416 /*
6417 ** We want a warning anytime we have:
6418 ** case xxx: ...
6419 ** yyy; <<<- no break or return
6420 ** case zzz: ...
6421 */
6422
6423 exprNode lastStmt = exprNode_lastStatement (e1);
6424
6425 if (exprNode_isDefined (lastStmt)
6426 && !exprNode_mustEscape (lastStmt)
6427 && !exprNode_mustBreak (lastStmt)
6428 && !exprNode_isCaseMarker (lastStmt)
6429 && !exprNode_isDefaultMarker (lastStmt)
6430 && !exprNode_isLabelMarker (lastStmt))
6431 {
6432 voptgenerror (FLG_CASEBREAK,
6433 cstring_makeLiteral
6434 ("Fall through case (no preceeding break)"),
6435 e2->loc);
6436 }
6437 }
6438 }
6439 }
6440
6441 exprNode_mergeUSs (ret, e2);
28bf4b0b 6442
616915dd 6443 usymtab_setExitCode (ret->exitCode);
6444
6445 if (ret->mustBreak)
6446 {
6447 usymtab_setMustBreak ();
6448 }
6449
6450 return ret;
6451}
6452
6453exprNode exprNode_createTok (/*@only@*/ lltok t)
6454{
28bf4b0b 6455 exprNode ret; /*@i23 if on same line, bad things happen...!@*/
6456 ret = exprNode_create (ctype_unknown);
616915dd 6457 ret->kind = XPR_TOK;
6458 ret->edata = exprData_makeTok (t);
6459 return ret;
6460}
6461
6462exprNode exprNode_statement (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6463{
6464 if (!exprNode_isError (e))
6465 {
6466 exprNode_checkStatement(e);
6467 }
6468
6469 return (exprNode_statementError (e, t));
6470}
6471
6472static exprNode exprNode_statementError (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6473{
6474 exprNode ret = exprNode_createPartialCopy (e);
6475
6476 if (!exprNode_isError (e))
6477 {
6478 if (e->kind != XPR_ASSIGN)
6479 {
6480 exprNode_checkUse (ret, e->sref, e->loc);
6481 }
6482
6483 ret->exitCode = e->exitCode;
6484 ret->canBreak = e->canBreak;
6485 ret->mustBreak = e->mustBreak;
6486 }
6487
6488 ret->edata = exprData_makeUop (e, t);
6489 ret->kind = XPR_STMT;
6490
6491 return ret;
6492}
6493
6494exprNode exprNode_checkExpr (/*@returned@*/ exprNode e)
6495{
6496 if (!exprNode_isError (e))
6497 {
6498 if (e->kind != XPR_ASSIGN)
6499 {
6500 exprNode_checkUse (e, e->sref, e->loc);
6501 }
6502 }
6503
6504 return e;
6505}
6506
6507void exprNode_produceGuards (exprNode pred)
6508{
6509 if (!exprNode_isError (pred))
6510 {
6511 if (ctype_isRealPointer (pred->typ))
6512 {
6513 pred->guards = guardSet_addTrueGuard (pred->guards, pred->sref);
6514 }
6515
6516 exprNode_checkUse (pred, pred->sref, pred->loc);
6517 exprNode_resetSref (pred);
6518 }
6519}
6520
6521exprNode exprNode_makeBlock (/*@only@*/ exprNode e)
6522{
6523 exprNode ret = exprNode_createPartialCopy (e);
6524
6525 if (!exprNode_isError (e))
6526 {
6527 ret->exitCode = e->exitCode;
6528 ret->canBreak = e->canBreak;
6529 ret->mustBreak = e->mustBreak;
6530 }
6531
6532 ret->edata = exprData_makeSingle (e);
6533 ret->kind = XPR_BLOCK;
6534 return ret;
6535}
6536
6537bool exprNode_isBlock (exprNode e)
6538{
6539 return (exprNode_isDefined (e)
6540 && ((e)->kind == XPR_BLOCK));
6541}
6542
6543bool exprNode_isAssign (exprNode e)
6544{
6545 if (exprNode_isDefined (e))
6546 {
6547 return (e->kind == XPR_ASSIGN);
6548 }
6549
6550 return FALSE;
6551}
6552
6553bool exprNode_isEmptyStatement (exprNode e)
6554{
6555 return (exprNode_isDefined (e)
6556 && (e->kind == XPR_TOK)
6557 && (lltok_isSemi (exprData_getTok (e->edata))));
6558}
6559
6560exprNode exprNode_if (/*@only@*/ exprNode pred, /*@only@*/ exprNode tclause)
6561{
6562 exprNode ret;
6563 bool emptyErr = FALSE;
6564
6565 if (context_maybeSet (FLG_IFEMPTY))
6566 {
6567 if (exprNode_isEmptyStatement (tclause))
6568 {
6569 emptyErr = optgenerror (FLG_IFEMPTY,
6570 cstring_makeLiteral
6571 ("Body of if statement is empty"),
6572 exprNode_loc (tclause));
6573 }
6574 }
6575
6576 if (!emptyErr && context_maybeSet (FLG_IFBLOCK))
6577 {
6578 if (exprNode_isDefined (tclause)
6579 && !exprNode_isBlock (tclause))
6580 {
6581 voptgenerror (FLG_IFBLOCK,
6582 message
6583 ("Body of if statement is not a block: %s",
6584 exprNode_unparse (tclause)),
6585 exprNode_loc (tclause));
6586 }
6587 }
6588
6589 if (exprNode_isError (pred))
6590 {
6591 if (exprNode_isError (tclause))
6592 {
6593 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
6594 }
6595 else
6596 {
6597 ret = exprNode_createPartialCopy (tclause);
6598 }
6599 }
6600 else
6601 {
6602 if (exprNode_mustEscape (pred))
6603 {
6604 voptgenerror
6605 (FLG_UNREACHABLE,
6606 message ("Predicate always exits: %s", exprNode_unparse (pred)),
6607 exprNode_loc (pred));
6608 }
6609
6610 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
6611 exprNode_checkUse (pred, pred->sref, pred->loc);
6612
6613 if (!exprNode_isError (tclause))
6614 {
6615 exprNode_mergeCondUSs (pred, tclause, exprNode_undefined);
6616 }
6617
6618 ret = exprNode_createPartialCopy (pred);
6619 }
6620
6621 ret->kind = XPR_IF;
6622 ret->edata = exprData_makePair (pred, tclause);
6623
6624 ret->exitCode = XK_UNKNOWN;
6625
6626 if (exprNode_isDefined (tclause))
6627 {
6628 ret->exitCode = exitkind_makeConditional (tclause->exitCode);
6629 ret->canBreak = tclause->canBreak;
6630 ret->sets = sRefSet_union (ret->sets, tclause->sets);
6631 ret->msets = sRefSet_union (ret->msets, tclause->msets);
6632 ret->uses = sRefSet_union (ret->uses, tclause->uses);
6633 }
6634
6635 ret->mustBreak = FALSE;
6636
6637 return ret;
6638}
6639
6640exprNode exprNode_ifelse (/*@only@*/ exprNode pred,
6641 /*@only@*/ exprNode tclause,
6642 /*@only@*/ exprNode eclause)
6643{
6644 exprNode ret;
6645 bool tEmptyErr = FALSE;
6646 bool eEmptyErr = FALSE;
6647
6648 if (context_maybeSet (FLG_IFEMPTY))
6649 {
6650 if (exprNode_isEmptyStatement (tclause))
6651 {
6652 tEmptyErr = optgenerror
6653 (FLG_IFEMPTY,
6654 cstring_makeLiteral
6655 ("Body of if clause of if statement is empty"),
6656 exprNode_loc (tclause));
6657 }
6658
6659 if (exprNode_isEmptyStatement (eclause))
6660 {
6661 eEmptyErr = optgenerror
6662 (FLG_IFEMPTY,
6663 cstring_makeLiteral
6664 ("Body of else clause of if statement is empty"),
6665 exprNode_loc (eclause));
6666 }
6667 }
6668
6669 if (context_maybeSet (FLG_IFBLOCK))
6670 {
6671 if (!tEmptyErr
6672 && exprNode_isDefined (tclause)
6673 && !exprNode_isBlock (tclause))
6674 {
6675 voptgenerror (FLG_IFBLOCK,
6676 message
6677 ("Body of if clause of if statement is not a block: %s",
6678 exprNode_unparse (tclause)),
6679 exprNode_loc (tclause));
6680 }
6681
6682 if (!eEmptyErr
6683 && exprNode_isDefined (eclause)
6684 && !exprNode_isBlock (eclause)
6685 && !(eclause->kind == XPR_IF)
6686 && !(eclause->kind == XPR_IFELSE))
6687 {
6688 voptgenerror
6689 (FLG_IFBLOCK,
6690 message
6691 ("Body of else clause of if statement is not a block: %s",
6692 exprNode_unparse (eclause)),
6693 exprNode_loc (eclause));
6694 }
6695 }
6696
6697 if (context_maybeSet (FLG_ELSEIFCOMPLETE))
6698 {
6699 if (exprNode_isDefined (eclause)
6700 && (eclause->kind == XPR_IF))
6701 {
6702 voptgenerror (FLG_ELSEIFCOMPLETE,
6703 message ("Incomplete else if logic (no final else): %s",
6704 exprNode_unparse (eclause)),
6705 exprNode_loc (eclause));
6706 }
6707 }
6708
6709 if (exprNode_isError (pred))
6710 {
6711 if (exprNode_isError (tclause))
6712 {
6713 if (exprNode_isError (eclause))
6714 {
6715 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
6716 }
6717 else
6718 {
6719 ret = exprNode_createPartialCopy (eclause);
6720 }
6721 }
6722 else
6723 {
6724 ret = exprNode_createPartialCopy (tclause);
6725 }
6726 }
6727 else /* pred is okay */
6728 {
6729 ret = exprNode_createPartialCopy (pred);
6730
6731 if (exprNode_mustEscape (pred))
6732 {
6733 voptgenerror
6734 (FLG_UNREACHABLE,
6735 message ("Predicate always exits: %s", exprNode_unparse (pred)),
6736 exprNode_loc (pred));
6737 }
6738
6739 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
6740 exprNode_checkUse (ret, pred->sref, pred->loc);
6741
6742 exprNode_mergeCondUSs (ret, tclause, eclause);
6743 }
6744
6745 ret->kind = XPR_IFELSE;
6746 ret->edata = exprData_makeCond (pred, tclause, eclause);
6747
6748 if (exprNode_isDefined (tclause) && exprNode_isDefined (eclause))
6749 {
6750 exprNode_combineControl (ret, tclause, eclause);
6751 ret->loc = fileloc_update (ret->loc, eclause->loc);
6752 }
6753
6754 return ret;
6755}
6756
6757/*
6758** *allpaths <- TRUE iff all executions paths must go through the switch
6759*/
6760
6761static bool
6762checkSwitchExpr (exprNode test, /*@dependent@*/ exprNode e, /*@out@*/ bool *allpaths)
6763{
6764 exprNodeSList el = exprNode_flatten (e);
6765 bool mustReturn = TRUE; /* find a branch that doesn't */
6766 bool thisReturn = FALSE;
6767 bool hasDefault = FALSE;
6768 bool hasAllMembers = FALSE;
6769 bool inSwitch = FALSE;
6770 bool isEnumSwitch = FALSE;
6771 bool canBreak = FALSE;
6772 bool fallThrough = FALSE;
6773 ctype ct = ctype_unknown;
6774 enumNameSList usedEnums;
6775 enumNameList enums;
6776
6777 if (exprNode_isDefined (test))
6778 {
6779 ctype ttype;
6780
6781 ct = test->typ;
6782 ttype = ctype_realType (ct);
6783
6784 if (ctype_isEnum (ttype))
6785 {
6786 isEnumSwitch = TRUE;
6787 enums = ctype_elist (ttype);
6788 usedEnums = enumNameSList_new ();
6789 }
6790 }
6791
6792 exprNodeSList_elements (el, current)
6793 {
6794 if (exprNode_isDefined (current))
6795 {
6796 switch (current->kind)
6797 {
6798 case XPR_FTDEFAULT:
6799 case XPR_DEFAULT:
6800 if (hasDefault)
6801 {
6802 voptgenerror
6803 (FLG_CONTROL,
6804 message ("Duplicate default cases in switch"),
6805 exprNode_loc (current));
6806 }
6807 /*@fallthrough@*/
6808 case XPR_FTCASE:
6809 case XPR_CASE:
6810 if (current->kind == XPR_DEFAULT || current->kind == XPR_FTDEFAULT)
6811 {
6812 hasDefault = TRUE;
6813 }
6814 else
6815 {
6816 if (isEnumSwitch)
6817 {
6818 exprNode st = exprData_getSingle (current->edata);
6819 uentry ue = exprNode_getUentry (st);
6820
6821 if (uentry_isValid (ue))
6822 {
6823 cstring cname = uentry_rawName (ue);
6824
6825 if (enumNameList_member (/*@-usedef@*/enums/*@=usedef@*/, cname))
6826 {
6827 if (enumNameSList_member
6828 (/*@-usedef@*/usedEnums/*@=usedef@*/, cname))
6829 {
6830 voptgenerror
6831 (FLG_CONTROL,
6832 message ("Duplicate case in switch: %s",
6833 cname),
6834 current->loc);
6835 }
6836 else
6837 {
6838 enumNameSList_addh (usedEnums, cname);
6839 }
6840 }
6841 else
6842 {
6843 voptgenerror
6844 (FLG_TYPE,
6845 message ("Case in switch not %s member: %s",
6846 ctype_unparse (ct), cname),
6847 current->loc);
6848 }
6849 }
6850 }
6851 }
6852
6853 if (inSwitch && !fallThrough)
6854 {
6855 if (!thisReturn || canBreak)
6856 {
6857 mustReturn = FALSE;
6858 }
6859 }
6860
6861 fallThrough = TRUE;
6862 inSwitch = TRUE;
6863 thisReturn = FALSE;
6864 canBreak = FALSE;
6865 /*@switchbreak@*/ break;
6866 default:
6867 thisReturn = thisReturn || exprNode_mustEscape (current);
6868 canBreak = canBreak || current->canBreak;
6869 if (canBreak) fallThrough = FALSE;
6870 }
6871 }
6872 } end_exprNodeSList_elements;
6873
6874 if (inSwitch) /* check the last one! */
6875 {
6876 if (!thisReturn || canBreak)
6877 {
6878 mustReturn = FALSE;
6879 }
6880 }
6881
6882 if (isEnumSwitch)
6883 {
6884 if (!hasDefault
6885 && (enumNameSList_size (/*@-usedef@*/usedEnums/*@=usedef@*/) !=
6886 enumNameList_size (/*@-usedef@*/enums/*@=usedef@*/)))
6887 {
6888 enumNameSList unused = enumNameSList_subtract (enums, usedEnums);
6889
6890 voptgenerror (FLG_MISSCASE,
6891 message ("Missing case%s in switch: %q",
6892 cstring_makeLiteralTemp
6893 ((enumNameSList_size (unused) > 1) ? "s" : ""),
6894 enumNameSList_unparse (unused)),
6895 g_currentloc);
6896
6897 enumNameSList_free (unused);
6898 }
6899 else
6900 {
6901 hasAllMembers = TRUE;
6902 *allpaths = TRUE;
6903 }
6904
6905 enumNameSList_free (usedEnums);
6906 }
6907 else
6908 {
6909 *allpaths = hasDefault;
6910 }
6911
6912 exprNodeSList_free (el);
6913 return ((hasDefault || hasAllMembers) && mustReturn);
6914}
6915
6916exprNode exprNode_switch (/*@only@*/ exprNode e, /*@only@*/ exprNode s)
6917{
6918 exprNode ret = exprNode_createPartialCopy (e);
6919 bool allpaths;
6920
6921 DPRINTF (("Switch: %s", exprNode_unparse (s)));
6922
6923 ret->kind = XPR_SWITCH;
6924 ret->edata = exprData_makePair (e, s);
6925
6926 if (!exprNode_isError (s))
6927 {
6928 exprNode fs = exprNode_firstStatement (s);
6929 ret->loc = fileloc_update (ret->loc, s->loc);
6930
6931 if (exprNode_isUndefined (fs)
6932 || exprNode_isCaseMarker (fs) || exprNode_isLabelMarker (fs)
6933 || exprNode_isDefaultMarker (fs)) {
6934 ;
6935 } else {
6936 voptgenerror (FLG_FIRSTCASE,
6937 message
6938 ("Statement after switch is not a case: %s", exprNode_unparse (fs)),
6939 fs->loc);
6940 }
6941 }
6942
6943 if (!exprNode_isError (e))
6944 {
6945 if (checkSwitchExpr (e, s, &allpaths))
6946 {
6947 ret->exitCode = XK_MUSTRETURN;
6948 }
6949 else
6950 {
6951 ret->exitCode = e->exitCode;
6952 }
6953
6954 ret->canBreak = e->canBreak;
6955 ret->mustBreak = e->mustBreak;
6956 }
6957 /*
6958 ** forgot this!
6959 ** exprNode.c:3883,32: Variable allpaths used before definition
6960 */
6961 else
6962 {
6963 allpaths = FALSE;
6964 }
6965
6966 DPRINTF (("Context exit switch!"));
6967 context_exitSwitch (ret, allpaths);
6968 DPRINTF (("Context exit switch done!"));
6969
6970 return ret;
6971}
6972
6973static void checkInfiniteLoop (/*@notnull@*/ exprNode test,
6974 /*@notnull@*/ exprNode body)
6975{
6976 sRefSet tuses = test->uses;
6977
6978 if (!sRefSet_isEmpty (test->uses))
6979 {
6980 sRefSet sets = sRefSet_newCopy (body->sets);
6981 bool hasError = TRUE;
6982 bool innerState = FALSE;
6983 sRefSet tuncon = sRefSet_undefined;
6984
6985 sets = sRefSet_union (sets, test->sets);
6986 sets = sRefSet_union (sets, body->msets);
6987 sets = sRefSet_union (sets, test->msets);
6988
6989 sRefSet_allElements (tuses, el)
6990 {
6991 if (sRef_isUnconstrained (el))
6992 {
6993 tuncon = sRefSet_insert (tuncon, el);
6994 }
6995 else
6996 {
6997 if (sRefSet_member (sets, el))
6998 {
6999 hasError = FALSE;
7000 break;
7001 }
7002 }
7003
7004 if (sRef_isInternalState (el)
7005 || sRef_isFileStatic (sRef_getRootBase (el)))
7006 {
7007 innerState = TRUE;
7008 }
7009 } end_sRefSet_allElements ;
7010
7011 if (hasError)
7012 {
7013 sRefSet suncon = sRefSet_undefined;
7014 bool sinner = FALSE;
7015
7016 sRefSet_allElements (sets, el)
7017 {
7018 if (sRef_isUnconstrained (el))
7019 {
7020 suncon = sRefSet_insert (suncon, el);
7021 }
7022 else if (sRef_isInternalState (el))
7023 {
7024 sinner = TRUE;
7025 }
7026 else
7027 {
7028 ;
7029 }
7030 } end_sRefSet_allElements ;
7031
7032 if (sinner && innerState)
7033 {
7034 ;
7035 }
7036 else if (sRefSet_isEmpty (tuncon)
7037 && sRefSet_isEmpty (suncon))
7038 {
7039 voptgenerror
7040 (FLG_INFLOOPS,
7041 message
7042 ("Suspected infinite loop. No value used in loop test (%q) "
7043 "is modified by test or loop body.",
7044 sRefSet_unparsePlain (tuses)),
7045 test->loc);
7046 }
7047 else
7048 {
7049 if (sRefSet_isEmpty (tuncon))
7050 {
7051 voptgenerror
7052 (FLG_INFLOOPSUNCON,
7053 message ("Suspected infinite loop. No condition values "
7054 "modified. Modification possible through "
7055 "unconstrained calls: %q",
7056 sRefSet_unparsePlain (suncon)),
7057 test->loc);
7058 }
7059 else
7060 {
7061 voptgenerror
7062 (FLG_INFLOOPSUNCON,
7063 message ("Suspected infinite loop. No condition values "
7064 "modified. Possible undetected dependency through "
7065 "unconstrained calls in loop test: %q",
7066 sRefSet_unparsePlain (tuncon)),
7067 test->loc);
7068 }
7069 }
7070 }
7071
7072 sRefSet_free (sets);
7073 }
7074}
7075
7076exprNode exprNode_while (/*@keep@*/ exprNode t, /*@keep@*/ exprNode b)
7077{
7078 exprNode ret;
7079 bool emptyErr = FALSE;
616915dd 7080
7081 if (context_maybeSet (FLG_WHILEEMPTY))
7082 {
7083 if (exprNode_isEmptyStatement (b))
7084 {
7085 emptyErr = optgenerror
7086 (FLG_WHILEEMPTY,
7087 cstring_makeLiteral
7088 ("Body of while statement is empty"),
7089 exprNode_loc (b));
7090 }
7091 }
7092
7093 if (!emptyErr && context_maybeSet (FLG_WHILEBLOCK))
7094 {
7095 if (exprNode_isDefined (b)
7096 && !exprNode_isBlock (b))
7097 {
7098 if (context_inIterDef ()
7099 && (b->kind == XPR_STMTLIST
7100 || b->kind == XPR_TOK))
7101 {
7102 ; /* no error */
7103 }
7104 else
7105 {
7106 voptgenerror (FLG_WHILEBLOCK,
7107 message
7108 ("Body of while statement is not a block: %s",
7109 exprNode_unparse (b)),
7110 exprNode_loc (b));
7111 }
7112 }
7113 }
7114
7115 if (exprNode_isError (t))
7116 {
7117 if (exprNode_isError (b))
7118 {
7119 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
7120 }
7121 else
7122 {
7123 ret = exprNode_createPartialCopy (b);
7124 }
7125 }
7126 else
7127 {
7128 exprNode test;
7129
7130 ret = exprNode_createPartialCopy (t);
7131
7132 llassert (t->kind == XPR_WHILEPRED);
7133
7134 test = exprData_getSingle (t->edata);
7135
7136 if (!exprNode_isError (b) && exprNode_isDefined (test))
7137 {
7138 if (context_maybeSet (FLG_INFLOOPS)
7139 || context_maybeSet (FLG_INFLOOPSUNCON))
7140 {
7141 /*
7142 ** check that some variable in the predicate is set by the body
7143 ** if the predicate uses any variables
7144 */
7145
7146 checkInfiniteLoop (test, b);
7147 }
7148
7149 exprNode_mergeUSs (ret, b);
7150
7151 if (exprNode_isDefined (b))
7152 {
7153 ret->exitCode = exitkind_makeConditional (b->exitCode);
7154 }
7155 }
7156 }
7157
7158 ret->edata = exprData_makePair (t, b);
7159 ret->kind = XPR_WHILE;
7160
7161 if (exprNode_isDefined (t) && exprNode_mustEscape (t))
7162 {
7163 voptgenerror
7164 (FLG_CONTROL,
7165 message ("Predicate always exits: %s", exprNode_unparse (t)),
7166 exprNode_loc (t));
7167 }
7168
7169 ret->exitCode = XK_NEVERESCAPE;
7170
7171 /*
7172 ** If loop is infinite, and there is no break inside,
7173 ** exit code is never reach.
7174 */
7175
7176 if (exprNode_knownIntValue (t))
7177 {
7178 if (!exprNode_isZero (t))
7179 {
7180 if (exprNode_isDefined (b))
7181 {
7182 if (!b->canBreak)
7183 {
7184 /* Really, it means never reached. */
7185 ret->exitCode = XK_MUSTEXIT;
7186 }
7187 }
7188 }
7189 }
7190 else
7191 {
7192 ;
7193 }
7194
7195 ret->canBreak = FALSE;
7196 ret->mustBreak = FALSE;
7197
7198 return ret;
7199}
7200
7201/*
7202** do { b } while (t);
7203**
7204** note: body passed as first argument
7205*/
7206
7207exprNode exprNode_doWhile (/*@only@*/ exprNode b, /*@only@*/ exprNode t)
7208{
7209 exprNode ret;
7210
7211 if (exprNode_isError (t))
7212 {
7213 if (exprNode_isError (b))
7214 {
7215 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
7216 }
7217 else
7218 {
7219 ret = exprNode_createPartialCopy (b);
7220
7221 ret->exitCode = exitkind_makeConditional (b->exitCode);
7222 exprNode_checkUse (ret, b->sref, b->loc);
7223 ret->exitCode = b->exitCode;
7224 ret->canBreak = b->canBreak;
7225 ret->mustBreak = b->mustBreak;
7226 }
7227 }
7228 else
7229 {
7230 ret = exprNode_createPartialCopy (t);
7231 exprNode_checkPred (cstring_makeLiteralTemp ("while"), t);
7232
7233 if (!exprNode_isError (b))
7234 {
7235 /*
7236 ** forgot the copy's --- why wasn't this detected??
7237 */
7238
28bf4b0b 7239 ret->sets = sRefSet_copyInto (ret->sets, b->sets);
7240 ret->msets = sRefSet_copyInto (ret->msets, b->msets);
7241 ret->uses = sRefSet_copyInto (ret->uses, b->uses);
616915dd 7242
7243 /* left this out --- causes and aliasing bug (infinite loop)
7244 should be detected?? */
7245
7246 exprNode_checkUse (ret, b->sref, b->loc);
7247 exprNode_mergeUSs (ret, t);
7248 exprNode_checkUse (ret, t->sref, t->loc);
7249
7250 ret->exitCode = b->exitCode;
7251 ret->canBreak = b->canBreak;
7252 ret->mustBreak = b->mustBreak;
7253 }
7254 }
7255
7256 context_exitDoWhileClause (t);
7257
7258 ret->kind = XPR_DOWHILE;
7259 ret->edata = exprData_makePair (t, b);
7260 return ret;
7261}
7262
7263exprNode exprNode_for (/*@keep@*/ exprNode inc, /*@keep@*/ exprNode body)
7264{
7265 exprNode ret;
7266 bool emptyErr = FALSE;
7267
7268 if (context_maybeSet (FLG_FOREMPTY))
7269 {
7270 if (exprNode_isEmptyStatement (body))
7271 {
7272 emptyErr = optgenerror
7273 (FLG_FOREMPTY,
7274 cstring_makeLiteral
7275 ("Body of for statement is empty"),
7276 exprNode_loc (body));
7277 }
7278 }
7279
7280 if (!emptyErr && context_maybeSet (FLG_FORBLOCK))
7281 {
7282 if (exprNode_isDefined (body)
7283 && !exprNode_isBlock (body))
7284 {
7285 if (context_inIterDef ()
7286 && (body->kind == XPR_STMTLIST
7287 || body->kind == XPR_TOK))
7288 {
7289 ; /* no error */
7290 }
7291 else
7292 {
7293 voptgenerror (FLG_FORBLOCK,
7294 message
7295 ("Body of for statement is not a block: %s",
7296 exprNode_unparse (body)),
7297 exprNode_loc (body));
7298 }
7299 }
7300 }
7301
7302 /*
7303 ** for ud purposes: (alreadly) init -> test -> (now) LOOP: body + inc + test
7304 */
7305
7306 if (exprNode_isError (body))
7307 {
7308 ret = exprNode_createPartialCopy (inc);
7309 }
7310 else
7311 {
7312 ret = exprNode_createPartialCopy (body);
7313
7314 ret->exitCode = exitkind_makeConditional (body->exitCode);
7315
7316 exprNode_mergeUSs (inc, body);
7317
7318 if (exprNode_isDefined (inc))
7319 {
7320 exprNode tmp;
7321
7322 context_setMessageAnnote (cstring_makeLiteral ("in post loop increment"));
7323
7324
7325 tmp = exprNode_effect (exprData_getTripleInc (inc->edata));
7326 exprNode_freeShallow (tmp);
7327
7328 context_clearMessageAnnote ();
7329 context_setMessageAnnote (cstring_makeLiteral ("in post loop test"));
7330
7331 tmp = exprNode_effect (exprData_getTripleTest (inc->edata));
7332 exprNode_freeShallow (tmp);
7333
7334 context_clearMessageAnnote ();
7335
28bf4b0b 7336 ret->uses = sRefSet_copyInto (ret->uses, inc->uses);
7337 ret->sets = sRefSet_copyInto (ret->sets, inc->sets);
7338 ret->msets = sRefSet_copyInto (ret->msets, inc->msets);
616915dd 7339 }
7340 }
7341
7342 ret->kind = XPR_FOR;
7343 ret->edata = exprData_makePair (inc, body);
7344
7345 if (exprNode_isDefined (inc)) {
7346 exprNode test = exprData_getTripleTest (inc->edata);
7347
7348 if (exprNode_isUndefined (test)) {
7349 if (exprNode_isDefined (body)) {
7350 if (!body->canBreak) {
7351 /* Really, it means never reached. */
7352 ret->exitCode = XK_MUSTEXIT;
7353 }
7354 }
7355 }
7356 }
7357
7358 return (ret);
7359}
7360
7361/*
7362** for (init; test; inc)
7363** ==>
7364** init;
7365** while (test) { body; inc; }
7366**
7367** Now: check use of init (may set vars for test)
7368** check use of test
7369** no checks on inc
7370_*/
7371
7372/*@observer@*/ guardSet exprNode_getForGuards (exprNode pred)
7373{
7374 exprNode test;
7375
7376 if (exprNode_isError (pred)) return guardSet_undefined;
7377
7378 llassert (pred->kind == XPR_FORPRED);
7379
7380 test = exprData_getTripleTest (pred->edata);
7381
7382 if (!exprNode_isError (test))
7383 {
7384 return (test->guards);
7385 }
7386
7387 return guardSet_undefined;
7388}
7389
7390exprNode exprNode_whilePred (/*@only@*/ exprNode test)
7391{
7392 exprNode ret = exprNode_createSemiCopy (test);
7393
7394 if (exprNode_isDefined (test))
7395 {
7396 exprNode_copySets (ret, test);
7397 exprNode_checkPred (cstring_makeLiteralTemp ("while"), test);
7398 exprNode_checkUse (ret, test->sref, test->loc);
7399
7400 exprNode_produceGuards (test);
7401
7402 ret->guards = guardSet_copy (test->guards);
7403 }
7404
7405 ret->edata = exprData_makeSingle (test);
7406 ret->kind = XPR_WHILEPRED;
7407 return ret;
7408}
7409
7410exprNode exprNode_forPred (/*@only@*/ exprNode init, /*@only@*/ exprNode test,
7411 /*@only@*/ exprNode inc)
7412{
7413 exprNode ret;
7414
7415 /*
7416 ** for ud purposes: init -> test -> LOOP: [ body, inc ]
7417 */
7418
7419 exprNode_checkPred (cstring_makeLiteralTemp ("for"), test);
7420
7421 if (!exprNode_isError (inc))
7422 {
7423 ret = exprNode_createPartialCopy (inc);
7424 }
7425 else
7426 {
7427 if (!exprNode_isError (init))
7428 {
7429 ret = exprNode_createPartialCopy (init);
7430 }
7431 else if (!exprNode_isError (test))
7432 {
7433 ret = exprNode_createPartialCopy (test);
7434 }
7435 else
7436 {
7437 ret = exprNode_createUnknown ();
7438 }
7439 }
7440
7441 exprNode_mergeUSs (ret, init);
7442
7443 if (exprNode_isDefined (init))
7444 {
7445 exprNode_checkUse (ret, init->sref, init->loc);
7446 }
7447
7448 exprNode_mergeUSs (ret, test);
7449
7450 if (exprNode_isDefined (test))
7451 {
7452 exprNode_checkUse (ret, test->sref, test->loc);
7453 }
7454
7455 ret->kind = XPR_FORPRED;
7456 ret->edata = exprData_makeFor (init, test, inc);
7457 return (ret);
7458}
7459
7460/*@notnull@*/ /*@only@*/ exprNode exprNode_goto (/*@only@*/ cstring label)
7461{
7462 exprNode ret = exprNode_createUnknown ();
7463
7464 if (context_inMacro ())
7465 {
7466 voptgenerror (FLG_MACROSTMT,
7467 message ("Macro %s uses goto (not functional)",
7468 context_inFunctionName ()),
7469 g_currentloc);
7470 }
7471
7472 ret->kind = XPR_GOTO;
7473 ret->edata = exprData_makeLiteral (label);
7474 ret->mustBreak = TRUE;
7475 ret->exitCode = XK_GOTO;
7476 ret->canBreak = TRUE;
7477 return ret;
7478}
7479
7480exprNode exprNode_continue (/*@only@*/ lltok l, int qcontinue)
7481{
7482 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7483
7484 ret->kind = XPR_CONTINUE;
7485 ret->edata = exprData_makeTok (l);
7486 ret->canBreak = TRUE;
7487 ret->mustBreak = TRUE;
7488
7489 if (qcontinue == QSAFEBREAK)
7490 {
7491 ; /* no checking */
7492 }
7493 else if (qcontinue == QINNERCONTINUE)
7494 {
7495 if (!context_inDeepLoop ())
7496 {
7497 voptgenerror
7498 (FLG_LOOPLOOPCONTINUE,
7499 cstring_makeLiteral ("Continue statement marked with innercontinue "
7500 "is not inside a nested loop"),
7501 exprNode_loc (ret));
7502 }
7503 }
7504 else if (qcontinue == BADTOK)
7505 {
7506 if (context_inDeepLoop ())
7507 {
7508 voptgenerror
7509 (FLG_LOOPLOOPCONTINUE,
7510 cstring_makeLiteral ("Continue statement in nested loop"),
7511 exprNode_loc (ret));
7512 }
7513 }
7514 else
7515 {
7516 llbuglit ("exprNode_continue: bad qcontinue");
7517 }
7518
7519 return ret;
7520}
7521
7522exprNode exprNode_break (/*@only@*/ lltok l, int bqual)
7523{
7524 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7525 clause breakClause = context_breakClause ();
7526
7527 ret->kind = XPR_BREAK;
7528 ret->edata = exprData_makeTok (l);
7529 ret->canBreak = TRUE;
7530 ret->mustBreak = TRUE;
7531
7532 if (breakClause == NOCLAUSE)
7533 {
7534 voptgenerror
7535 (FLG_SYNTAX,
7536 cstring_makeLiteral ("Break not inside while, for or switch statement"),
7537 exprNode_loc (ret));
7538 }
7539 else
7540 {
7541 if (bqual != BADTOK)
7542 {
7543 switch (bqual)
7544 {
7545 case QSAFEBREAK:
7546 break;
7547 case QINNERBREAK:
7548 if (breakClause == SWITCHCLAUSE)
7549 {
7550 if (!context_inDeepSwitch ())
7551 {
7552 voptgenerror (FLG_SYNTAX,
7553 cstring_makeLiteral
7554 ("Break preceded by innerbreak is not in a deep switch"),
7555 exprNode_loc (ret));
7556 }
7557 }
7558 else
7559 {
7560 if (!context_inDeepLoop ())
7561 {
7562 voptgenerror (FLG_SYNTAX,
7563 cstring_makeLiteral
7564 ("Break preceded by innerbreak is not in a deep loop"),
7565 exprNode_loc (ret));
7566 }
7567 }
7568 break;
7569 case QLOOPBREAK:
7570 if (breakClause == SWITCHCLAUSE)
7571 {
7572 voptgenerror (FLG_SYNTAX,
7573 cstring_makeLiteral
7574 ("Break preceded by loopbreak is breaking a switch"),
7575 exprNode_loc (ret));
7576 }
7577 break;
7578 case QSWITCHBREAK:
7579 if (breakClause != SWITCHCLAUSE)
7580 {
7581 voptgenerror
7582 (FLG_SYNTAX,
7583 message ("Break preceded by switchbreak is breaking %s",
7584 cstring_makeLiteralTemp
7585 ((breakClause == WHILECLAUSE
7586 || breakClause == DOWHILECLAUSE) ? "a while loop"
7587 : (breakClause == FORCLAUSE) ? "a for loop"
7588 : (breakClause == ITERCLAUSE) ? "an iterator"
7589 : "<error loop>")),
7590 exprNode_loc (ret));
7591 }
7592 break;
7593 BADDEFAULT;
7594 }
7595 }
7596 else
7597 {
7598 if (breakClause == SWITCHCLAUSE)
7599 {
7600 clause nextBreakClause = context_nextBreakClause ();
7601
7602 switch (nextBreakClause)
7603 {
7604 case NOCLAUSE: break;
7605 case WHILECLAUSE:
7606 case DOWHILECLAUSE:
7607 case FORCLAUSE:
7608 case ITERCLAUSE:
7609 voptgenerror
7610 (FLG_LOOPSWITCHBREAK,
7611 cstring_makeLiteral ("Break statement in switch inside loop"),
7612 exprNode_loc (ret));
7613 break;
7614 case SWITCHCLAUSE:
7615 voptgenerror
7616 (FLG_SWITCHSWITCHBREAK,
7617 cstring_makeLiteral ("Break statement in switch inside switch"),
7618 exprNode_loc (ret));
7619 break;
7620 BADDEFAULT;
7621 }
7622 }
7623 else
7624 {
7625 if (context_inDeepLoop ())
7626 {
7627 voptgenerror
7628 (FLG_LOOPLOOPBREAK,
7629 cstring_makeLiteral ("Break statement in nested loop"),
7630 exprNode_loc (ret));
7631 }
7632 else
7633 {
7634 if (context_inDeepLoopSwitch ())
7635 {
7636 voptgenerror
7637 (FLG_SWITCHLOOPBREAK,
7638 cstring_makeLiteral ("Break statement in loop inside switch"),
7639 exprNode_loc (ret));
7640 }
7641 }
7642 }
7643 }
7644 }
7645
7646 return ret;
7647}
7648
7649exprNode exprNode_nullReturn (/*@only@*/ lltok t)
7650{
7651 fileloc loc = lltok_getLoc (t);
7652 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
7653
7654 context_returnFunction ();
7655 exprChecks_checkNullReturn (loc);
7656
7657 ret->kind = XPR_NULLRETURN;
7658 ret->edata = exprData_makeTok (t);
7659 ret->exitCode = XK_MUSTRETURN;
7660 return ret;
7661}
7662
7663exprNode exprNode_return (/*@only@*/ exprNode e)
7664{
7665 exprNode ret;
7666
7667 if (exprNode_isError (e))
7668 {
7669 ret = exprNode_createUnknown ();
7670 }
7671 else
7672 {
7673 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (e->loc));
7674
7675 exprNode_checkUse (ret, e->sref, e->loc);
7676 exprNode_checkReturn (e);
7677 }
7678
7679 context_returnFunction ();
7680 ret->kind = XPR_RETURN;
7681 ret->edata = exprData_makeSingle (e);
7682 ret->exitCode = XK_MUSTRETURN;
7683
7684 return (ret);
7685}
7686
7687exprNode exprNode_comma (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
7688{
7689 exprNode ret;
7690
7691 if (exprNode_isError (e1))
7692 {
7693 if (exprNode_isError (e2))
7694 {
7695 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
7696 }
7697 else
7698 {
7699 ret = exprNode_createPartialCopy (e2);
7700 exprNode_checkUse (ret, e2->sref, e2->loc);
7701 ret->sref = e2->sref;
7702 }
7703 }
7704 else
7705 {
7706 ret = exprNode_createPartialCopy (e1);
7707
7708 exprNode_checkUse (ret, e1->sref, e1->loc);
7709
7710 if (!exprNode_isError (e2))
7711 {
7712 exprNode_mergeUSs (ret, e2);
7713 exprNode_checkUse (ret, e2->sref, e2->loc);
7714 ret->sref = e2->sref;
7715 }
7716 }
7717
7718 ret->kind = XPR_COMMA;
7719 ret->edata = exprData_makePair (e1, e2);
7720
7721 if (exprNode_isDefined (e1))
7722 {
7723 if (exprNode_isDefined (e2))
7724 {
7725 ret->typ = e2->typ;
7726
7727 if (exprNode_mustEscape (e1) || e1->mustBreak)
7728 {
7729 voptgenerror
7730 (FLG_UNREACHABLE,
7731 message ("Second clause of comma expression is unreachable: %s",
7732 exprNode_unparse (e2)),
7733 exprNode_loc (e2));
7734 }
7735
7736 ret->exitCode = exitkind_combine (e1->exitCode, e2->exitCode);
7737 ret->mustBreak = e1->mustBreak || e2->mustBreak;
7738 ret->canBreak = e1->canBreak || e2->canBreak;
7739 }
7740 else
7741 {
7742 if (exprNode_mustEscape (e1) || e1->mustBreak)
7743 {
7744 voptgenerror
7745 (FLG_UNREACHABLE,
7746 message ("Second clause of comma expression is unreachable: %s",
7747 exprNode_unparse (e2)),
7748 exprNode_loc (e2));
7749 }
7750
7751 ret->exitCode = e1->exitCode;
7752 ret->canBreak = e1->canBreak;
7753 }
7754 }
7755 else
7756 {
7757 if (exprNode_isDefined (e2))
7758 {
7759 ret->exitCode = e2->exitCode;
7760 ret->mustBreak = e2->mustBreak;
7761 ret->canBreak = e2->canBreak;
7762 }
7763 }
7764
7765 return (ret);
7766}
7767
7768static bool exprNode_checkOneInit (/*@notnull@*/ exprNode el, exprNode val)
7769{
7770 ctype t1 = exprNode_getType (el);
7771 ctype t2 = exprNode_getType (val);
7772 bool hasError = FALSE;
7773
7774 if (ctype_isUnknown (t1))
7775 {
7776 voptgenerror (FLG_IMPTYPE,
7777 message ("Variable has unknown (implicitly int) type: %s",
7778 exprNode_unparse (el)),
7779 el->loc);
7780
7781 t1 = ctype_int;
7782 el->typ = ctype_int;
7783 }
7784
7785 if (exprNode_isDefined (val) && val->kind == XPR_INITBLOCK)
7786 {
7787 exprNodeList vals = exprData_getArgs (val->edata);
7788
7789 if (ctype_isRealAP (t1))
7790 {
7791 int i = 0;
7792 int nerrors = 0;
7793
b072092f 7794 /*@i423 check number of entries int a[3] = { 1, 2, 3, 4 } ; */
7795
616915dd 7796 exprNodeList_elements (vals, oneval)
7797 {
7798 cstring istring = message ("%d", i);
7799 exprNode newel =
7800 exprNode_arrayFetch
7801 (exprNode_fakeCopy (el),
7802 exprNode_numLiteral (ctype_int, istring,
7803 fileloc_copy (el->loc), i));
7804
7805 if (exprNode_isDefined (newel))
7806 {
7807 if (exprNodeList_size (vals) == 1
7808 && ctype_isString (exprNode_getType (oneval))
7809 && ctype_isChar (exprNode_getType (newel)))
7810 {
7811 exprNode_freeIniter (newel);
7812 }
7813 else
7814 {
7815 if (exprNode_checkOneInit (newel, oneval))
7816 {
7817 hasError = TRUE;
7818 nerrors++;
7819
7820 if (nerrors > 3 && exprNodeList_size (vals) > 6)
7821 {
7822 llgenmsg
7823 (message ("Additional initialization errors "
7824 "for %s not reported",
7825 exprNode_unparse (el)),
7826 exprNode_loc (el));
7827 exprNode_freeIniter (newel);
7828 break;
7829 }
7830 else
7831 {
7832 exprNode_freeIniter (newel);
7833 }
7834 }
7835 else
7836 {
7837 exprNode_freeIniter (newel);
7838 }
7839 }
7840 }
7841
7842 cstring_free (istring);
7843 i++;
7844 /*@-branchstate@*/
7845 } end_exprNodeList_elements;
7846 /*@=branchstate@*/
7847 }
7848 else if (ctype_isStruct (ctype_realType (t1)))
7849 {
7850 uentryList fields = ctype_getFields (t1);
7851 int i = 0;
7852
7853 if (uentryList_size (fields) != exprNodeList_size (vals))
7854 {
7855 if (uentryList_size (fields) > exprNodeList_size (vals))
7856 {
7857 hasError = optgenerror
7858 (FLG_FULLINITBLOCK,
7859 message ("Initializer block for "
28bf4b0b 7860 "%s has %d field%&, but %s has %d field%&: %q",
616915dd 7861 exprNode_unparse (el),
7862 exprNodeList_size (vals),
7863 ctype_unparse (t1),
7864 uentryList_size (fields),
7865 exprNodeList_unparse (vals)),
7866 val->loc);
7867 }
7868 else
7869 {
7870 hasError = optgenerror
7871 (FLG_TYPE,
7872 message ("Initializer block for "
28bf4b0b 7873 "%s has %d field%&, but %s has %d field%&: %q",
616915dd 7874 exprNode_unparse (el),
7875 exprNodeList_size (vals),
7876 ctype_unparse (t1),
7877 uentryList_size (fields),
7878 exprNodeList_unparse (vals)),
7879 val->loc);
7880 }
7881 }
7882 else
7883 {
7884 exprNodeList_elements (vals, oneval)
7885 {
7886 uentry thisfield = uentryList_getN (fields, i);
7887 exprNode newel =
28bf4b0b 7888 exprNode_fieldAccessAux (exprNode_fakeCopy (el),
7889 exprNode_loc (el),
7890 uentry_getName (thisfield));
616915dd 7891
7892 if (exprNode_isDefined (newel))
7893 {
7894 if (exprNode_checkOneInit (newel, oneval))
7895 {
7896 hasError = TRUE;
7897 }
7898
7899 exprNode_freeIniter (newel);
7900 }
7901
7902 i++;
7903 } end_exprNodeList_elements;
7904 }
7905 }
7906 else
7907 {
7908 hasError = optgenerror
7909 (FLG_TYPE,
7910 message ("Initializer block used for "
7911 "%s where %t is expected: %s",
7912 exprNode_unparse (el), t1, exprNode_unparse (val)),
7913 val->loc);
7914 }
7915 }
7916 else
7917 {
7918 if (exprNode_isDefined (val))
7919 {
7920 doAssign (el, val, TRUE);
7921
7922 if (!exprNode_matchType (t1, val))
7923 {
7924 hasError = gentypeerror
7925 (t1, val, t2, el,
7926 message ("Initial value of %s is type %t, "
7927 "expects %t: %s",
7928 exprNode_unparse (el),
7929 t2, t1, exprNode_unparse (val)),
7930 val->loc);
7931 }
7932 }
7933 }
7934
7935 return hasError;
7936}
7937
28bf4b0b 7938static exprNode
7939exprNode_makeInitializationAux (/*@temp@*/ idDecl t)
7940{
7941 exprNode ret;
7942
7943 if (usymtab_exists (idDecl_observeId (t)))
7944 {
7945 uentry ue = usymtab_lookup (idDecl_observeId (t));
7946 ret = exprNode_createId (ue);
7947
7948 /*@i723 don't do this...but why? */
7949# if 0
7950 ct = ctype_realishType (ret->typ);
7951
7952 DPRINTF (("Type: %s", ctype_unparse (ret->typ)));
7953
7954 if (ctype_isUnknown (ct))
7955 {
7956 if (uentry_isAnyTag (ue))
7957 {
7958 voptgenerror
7959 (FLG_IMPTYPE,
7960 message ("%s used but not previously declared: %s",
7961 uentry_ekindName (ue),
7962 idDecl_getName (t)),
7963 g_currentloc);
7964
7965 }
7966 else
7967 {
7968 voptgenerror
7969 (FLG_IMPTYPE,
7970 message ("Variable has unknown (implicitly int) type: %s",
7971 idDecl_getName (t)),
7972 g_currentloc);
7973 }
7974
7975 ct = ctype_int;
7976 }
7977# endif
7978 }
7979 else
7980 {
7981 uentry ue = uentry_makeUnrecognized (idDecl_observeId (t),
7982 g_currentloc);
7983 ret = exprNode_fromIdentifierAux (ue);
7984
7985 /*
7986 ** No error - this happens in old style declarations:
7987
7988 voptgenerror
7989 (FLG_UNRECOG,
7990 message ("Unrecognized identifier in intializer: %s", idDecl_observeId (t)),
7991 g_currentloc);
7992
7993 **
7994 */
7995 }
7996
7997 exprData_free (ret->edata, ret->kind);
7998 ret->edata = exprData_undefined;
7999 ret->exitCode = XK_NEVERESCAPE;
8000 ret->mustBreak = FALSE;
8001 ret->kind = XPR_INIT;
8002 return ret;
8003}
8004
8005exprNode exprNode_makeEmptyInitialization (/*@only@*/ idDecl t)
8006{
8007 exprNode ret = exprNode_makeInitializationAux (t);
8008 llassert (ret->edata == exprData_undefined);
8009 ret->edata = exprData_makeInit (t, exprNode_undefined);
8010 return ret;
8011}
8012
616915dd 8013exprNode exprNode_makeInitialization (/*@only@*/ idDecl t,
8014 /*@only@*/ exprNode e)
8015{
8016 uentry ue = usymtab_lookup (idDecl_observeId (t));
28bf4b0b 8017 exprNode ret = exprNode_makeInitializationAux (t);
8018 fileloc loc = exprNode_loc (e);
b072092f 8019
616915dd 8020 if (exprNode_isError (e))
8021 {
8022 e = exprNode_createUnknown ();
28bf4b0b 8023 idDecl_free (t);
616915dd 8024
8025 /* error: assume initializer is defined */
28bf4b0b 8026 sRef_setDefined (ret->sref, g_currentloc);
616915dd 8027 }
8028 else
8029 {
28bf4b0b 8030 ctype ct = ctype_realishType (ret->typ);
8031
616915dd 8032 /*
8033 ** evs - 9 Apr 1995
8034 **
8035 ** was addSafeUse --- what's the problem?
8036 **
8037 ** int x = 3, y = x ?
8038 */
8039
28bf4b0b 8040 exprData_free (ret->edata, ret->kind);
8041 ret->edata = exprData_makeInit (t, e);
8042
616915dd 8043 exprNode_checkUse (ret, e->sref, e->loc);
8044
8045 if (ctype_isUnknown (e->typ) && uentry_isValid (ue))
8046 {
8047 exprNode lhs = exprNode_createId (ue);
8048
8049 /*
8050 ** static storage should be undefined before initializing
8051 */
8052
8053 if (uentry_isStatic (ue))
8054 {
8055 sRef_setDefState (lhs->sref, SS_PARTIAL, fileloc_undefined);
8056 }
8057
8058 (void) exprNode_checkOneInit (lhs, e);
8059
8060 if (uentry_isStatic (ue))
8061 {
8062 sRef_setDefState (lhs->sref, SS_DEFINED, fileloc_undefined);
8063 }
8064
8065 exprNode_free (lhs);
8066 }
8067 else
8068 {
8069 if (!exprNode_matchType (ct, e))
8070 {
8071 if (exprNode_isZero (e) && ctype_isArrayPtr (ct))
8072 {
8073 ;
8074 }
8075 else
8076 {
8077 (void) gentypeerror
8078 (exprNode_getType (e), e, exprNode_getType (ret), ret,
8079 message
28bf4b0b 8080 ("Variable %q initialized to type %t, expects %t: %s",
8081 uentry_getName (ue), exprNode_getType (e),
616915dd 8082 exprNode_getType (ret),
8083 exprNode_unparse (e)),
8084 e->loc);
8085 }
8086 }
8087 }
8088
8089 if (uentry_isStatic (ue))
8090 {
8091 sRef_setDefState (ret->sref, SS_PARTIAL, fileloc_undefined);
8092 }
8093
8094 doAssign (ret, e, TRUE);
8095
8096 if (uentry_isStatic (ue))
8097 {
8098 sRef_setDefState (ret->sref, SS_DEFINED, fileloc_undefined);
8099 }
8100 }
8101
8102 if (context_inIterDef ())
8103 {
8104 /* should check if it is yield */
8105 uentry_setUsed (ue, loc);
8106 }
8107 else
8108 {
28bf4b0b 8109 ;
616915dd 8110 }
8111
616915dd 8112 exprNode_mergeUSs (ret, e);
8113 return ret;
8114}
8115
8116exprNode exprNode_iter (/*@observer@*/ uentry name,
8117 /*@only@*/ exprNodeList alist,
8118 /*@only@*/ exprNode body,
8119 /*@observer@*/ uentry end)
8120{
8121 exprNode ret;
8122 cstring iname;
8123
8124 llassert (uentry_isValid (name));
8125
8126 uentry_setUsed (name, exprNode_loc (body));
8127
8128 ret = exprNode_createPartialCopy (body);
8129 iname = uentry_getName (name);
8130
8131 if (uentry_isInvalid (end))
8132 {
8133 llerror (FLG_ITER,
8134 message ("Iter %s not balanced with end_%s", iname, iname));
8135 }
8136 else
8137 {
8138 cstring ename = uentry_getName (end);
8139
8140 if (!cstring_equalPrefix (ename, "end_"))
8141 {
8142 llerror (FLG_ITER, message ("Iter %s not balanced with end_%s: %s",
8143 iname, iname, ename));
8144 }
8145 else
8146 {
8147 if (!cstring_equal (iname, cstring_suffix (ename, 4)))
8148 {
8149 llerror (FLG_ITER,
8150 message ("Iter %s not balanced with end_%s: %s",
8151 iname, iname, ename));
8152 }
8153 }
8154
8155 cstring_free (ename);
8156 }
8157
8158 context_exitIterClause (body);
8159
8160 ret->kind = XPR_ITER;
8161 ret->edata = exprData_makeIter (name, alist, body, end);
8162
8163 if (uentry_isIter (name))
8164 {
8165 (void) checkArgsReal (name, body,
8166 uentry_getParams (name), alist, TRUE, ret);
8167 }
8168
8169 cstring_free (iname);
8170
8171 return ret;
8172}
8173
8174exprNode
8175exprNode_iterNewId (/*@only@*/ cstring s)
8176{
8177 exprNode e = exprNode_new ();
8178 uentry ue = uentryList_getN (uentry_getParams (getCurrentIter ()), iterParamNo ());
8179
8180 llassert (processingIterVars ());
8181
8182 e->loc = context_getSaveLocation ();
8183
8184 if (fileloc_isUndefined (e->loc))
8185 {
8186 fileloc_free (e->loc);
8187 e->loc = fileloc_copy (g_currentloc);
8188 }
8189
8190 e->uses = sRefSet_new ();
8191 e->sets = sRefSet_new ();
8192 e->msets = sRefSet_new ();
8193 e->kind = XPR_VAR;
8194 e->val = multiVal_unknown ();
8195 e->guards = guardSet_new ();
8196 e->sref = defref;
8197 e->isJumpPoint = FALSE;
8198 e->exitCode = XK_NEVERESCAPE;
8199
8200 /*> missing fields, detected by lclint <*/
8201 e->canBreak = FALSE;
8202 e->mustBreak = FALSE;
8203 e->etext = cstring_undefined;
8204
8205 if (uentry_isYield (ue))
8206 {
8207 uentry uue = uentry_makeVariable (s, uentry_getType (ue),
8208 fileloc_copy (e->loc),
8209 FALSE);
8210 sRef sr;
8211
8212 uue = usymtab_supEntrySrefReturn (uue);
8213
8214 sr = uentry_getSref (uue);
8215 sRef_mergeStateQuiet (sr, uentry_getSref (ue));
8216 sr = uentry_getSref (uue);
8217 sRef_setDefined (sr, e->loc);
8218
8219 e->typ = uentry_getType (uue);
8220 e->sref = sr;
8221 e->edata = exprData_makeId (uue);
8222 uentry_setUsed (uue, g_currentloc);
8223 }
8224 else
8225 {
8226 uentry uue;
8227
8228 sRef_setGlobalScope ();
8229 uue = uentry_makeVariableLoc (s, ctype_unknown);
8230
8231 e->typ = ctype_unknown;
8232 e->edata = exprData_makeId (uue);
8233
8234 uentry_setUsed (uue, e->loc);
8235 uentry_setHasNameError (uue);
8236
8237 if (context_getFlag (FLG_REPEATUNRECOG))
8238 {
8239 uentry_markOwned (uue);
8240 }
8241 else
8242 {
8243 usymtab_supGlobalEntry (uue);
8244 }
8245
8246 sRef_clearGlobalScope ();
8247
8248 voptgenerror (FLG_UNRECOG, message ("Unrecognized identifier: %s", s),
8249 e->loc);
8250 }
8251
8252
8253 cstring_free (s);
84c9ffbf 8254
8255 exprNode_defineConstraints(e);
616915dd 8256 return (e);
8257}
8258
8259exprNode
8260exprNode_iterExpr (/*@returned@*/ exprNode e)
8261{
8262 if (!processingIterVars ())
8263 {
8264 llcontbuglit ("checkIterParam: not in iter");
8265 return e;
8266 }
8267
8268 if (uentry_isYield (uentryList_getN (uentry_getParams (getCurrentIter ()),
8269 iterParamNo ())))
8270 {
8271 if (exprNode_isDefined (e))
8272 {
8273 if (fileloc_isDefined (e->loc))
8274 {
8275 voptgenerror
8276 (FLG_ITER,
8277 message ("Yield parameter is not simple identifier: %s",
8278 exprNode_unparse (e)),
8279 e->loc);
8280 }
8281 else
8282 {
8283 voptgenerror
8284 (FLG_ITER,
8285 message ("Yield parameter is not simple identifier: %s",
8286 exprNode_unparse (e)),
8287 g_currentloc);
8288
8289 }
8290 }
8291 }
8292 return e;
8293}
8294
8295exprNode
8296exprNode_iterId (/*@observer@*/ uentry c)
8297{
8298 uentry ue;
8299
8300 llassert (processingIterVars ());
8301
8302 ue = uentryList_getN (uentry_getParams (getCurrentIter ()),
8303 iterParamNo ());
8304
8305 if (uentry_isYield (ue))
8306 {
8307 ctype ct = uentry_getType (ue);
8308 exprNode e = exprNode_createPlain (ct);
8309 cstring name = uentry_getName (c);
8310 uentry le = uentry_makeVariable (name, ct, fileloc_undefined, FALSE);
8311
8312 uentry_setUsed (ue, g_currentloc);
8313 uentry_setHasNameError (ue);
8314
8315 cstring_free (name);
8316
8317 e->kind = XPR_VAR;
8318 e->edata = exprData_makeId (le);
8319 e->loc = context_getSaveLocation ();
8320 e->sref = uentry_getSref (le);
8321
8322 usymtab_supEntrySref (le);
8323
8324 if (!context_inHeader ())
8325 {
8326 if (optgenerror
8327 (FLG_ITER,
8328 message ("Yield parameter shadows local declaration: %q",
8329 uentry_getName (c)),
8330 fileloc_isDefined (e->loc) ? e->loc : g_currentloc))
8331 {
8332 uentry_showWhereDeclared (c);
8333 }
8334 }
8335
8336 return e;
8337 }
8338
8339 return (exprNode_fromIdentifierAux (c));
8340}
8341
8342exprNode exprNode_iterStart (/*@observer@*/ uentry name, /*@only@*/ exprNodeList alist)
8343{
8344 exprNode ret = exprNode_create (ctype_unknown);
8345
8346 ret->kind = XPR_ITERCALL;
8347 ret->edata = exprData_makeIterCall (name, alist);
8348
8349 if (uentry_isIter (name))
8350 {
8351 uentryList params = uentry_getParams (name);
8352
8353 if (context_inIterDef ()
8354 && uentryList_size (params) == exprNodeList_size (alist))
8355 {
8356 int i = 0;
8357
8358 exprNodeList_elements (alist, arg)
8359 {
8360 uentry parg = uentryList_getN (params, i);
8361
8362 if (uentry_isYield (parg))
8363 {
8364 uentry ue = exprNode_getUentry (arg);
8365
8366 if (uentry_isValid (ue))
8367 {
8368 ;
8369 }
8370 }
8371
8372 i++;
8373 } end_exprNodeList_elements;
8374 }
8375
8376 (void) checkArgsReal (name, ret, params, alist, TRUE, ret);
8377 checkUnspecCall (ret, params, alist);
8378 }
8379
8380 return ret;
8381}
8382
8383/*@exposed@*/ sRef exprNode_getSref (exprNode e)
8384{
8385 if (exprNode_isDefined (e))
8386 {
8387 /*@access sRef@*/
8388 if (e->sref == defref) /*@noaccess sRef@*/
8389 {
8390 /*@-mods@*/
8391 e->sref = sRef_makeUnknown ();
8392 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
8393 /*@=mods@*/
8394 return e->sref;
8395 }
8396 else
8397 {
8398 return e->sref;
8399 }
8400 }
8401 else
8402 {
8403 return sRef_undefined;
8404 }
8405}
8406
8407/*@observer@*/ cstring
8408exprNode_unparseFirst (exprNode e)
8409{
8410 if (exprNode_isDefined (e))
8411 {
8412 cstring ret;
8413
8414 if (e->kind == XPR_STMTLIST
8415 || e->kind == XPR_COMMA || e->kind == XPR_COND)
8416 {
8417 exprNode first = exprData_getPairA (e->edata);
8418
8419 if (exprNode_isDefined (first))
8420 {
8421 return (exprNode_unparseFirst (exprData_getPairA (e->edata)));
8422 }
8423 else
8424 {
8425 return (cstring_makeLiteralTemp ("..."));
8426 }
8427 }
8428
8429 ret = cstring_elide (exprNode_unparse (e), 20);
8430 cstring_markOwned (ret);
8431
8432 return (ret);
8433 }
8434 else
8435 {
8436 return cstring_makeLiteralTemp ("<error>");
8437 }
8438}
8439
8440/*@observer@*/ cstring
28bf4b0b 8441exprNode_unparse (/*@temp@*/ exprNode e)
616915dd 8442{
8443 if (exprNode_isError (e))
8444 {
8445 return cstring_makeLiteralTemp ("<error>");
8446 }
8447
8448 if (cstring_isDefined (e->etext))
8449 {
8450 return e->etext;
8451 }
8452 else
8453 {
8454 cstring ret = exprNode_doUnparse (e);
8455
8456 /*@-modifies@*/ /* benevolent */
8457 e->etext = ret;
8458 /*@=modifies@*/
8459 return ret;
8460 }
8461}
8462
8463/*@observer@*/ fileloc
8464exprNode_loc (exprNode e)
8465{
8466 if (exprNode_isError (e))
8467 {
8468 return (g_currentloc);
8469 }
8470 else
8471 {
8472 return (e->loc);
8473 }
8474}
8475
8476/*
8477** executes exprNode e
8478** recursively rexecutes as though in original parse using
8479** information in e->edata
8480*/
8481
8482static /*@only@*/ exprNodeList exprNodeList_effect (exprNodeList e)
8483{
8484 exprNodeList ret = exprNodeList_new ();
8485
8486 exprNodeList_elements (e, current)
8487 {
8488 exprNodeList_addh (ret, exprNode_effect (current));
8489 } end_exprNodeList_elements;
8490
8491 return ret;
8492}
8493
8494static /*@only@*/ exprNode exprNode_effect (exprNode e)
8495 /*@globals internalState@*/
8496{
8497 bool innerEffect = inEffect;
8498 exprNode ret;
8499 exprData data;
8500
8501 inEffect = TRUE;
8502
8503 context_clearJustPopped ();
8504
8505 if (exprNode_isError (e))
8506 {
8507 ret = exprNode_undefined;
8508 }
8509 else
8510 {
8511 /*
8512 ** Turn off expose and dependent transfer checking.
8513 ** Need to pass exposed internal nodes,
8514 ** [ copying would be a waste! ]
8515 ** [ Actually, I think I wasted a lot more time than its worth ]
8516 ** [ trying to do this. ]
8517 */
8518
8519 /*@-exposetrans@*/
8520 /*@-observertrans@*/
8521 /*@-dependenttrans@*/
8522
8523 data = e->edata;
8524
8525 switch (e->kind)
8526 {
8527 case XPR_PARENS:
8528 ret = exprNode_addParens (exprData_getUopTok (data),
8529 exprNode_effect (exprData_getUopNode (data)));
8530 break;
8531 case XPR_ASSIGN:
8532 ret = exprNode_assign (exprNode_effect (exprData_getOpA (data)),
8533 exprNode_effect (exprData_getOpB (data)),
8534 exprData_getOpTok (data));
8535 break;
8536 case XPR_INITBLOCK:
8537 ret = exprNode_undefined;
8538 break;
8539 case XPR_CALL:
8540 ret = exprNode_functionCall (exprNode_effect (exprData_getFcn (data)),
8541 exprNodeList_effect (exprData_getArgs (data)));
8542 break;
8543 case XPR_EMPTY:
8544 ret = e;
8545 break;
8546
8547 case XPR_LABEL:
8548 ret = e;
8549 break;
8550
8551 case XPR_CONST:
8552 case XPR_VAR:
8553 {
8554 cstring id = exprData_getId (data);
8555 uentry ue = usymtab_lookupSafe (id);
8556
8557 ret = exprNode_fromIdentifierAux (ue);
8558 ret->loc = fileloc_update (ret->loc, e->loc);
8559 break;
8560 }
8561 case XPR_BODY:
8562 ret = e;
8563 break;
8564 case XPR_FETCH:
8565 ret = exprNode_arrayFetch (exprNode_effect (exprData_getPairA (data)),
8566 exprNode_effect (exprData_getPairB (data)));
8567 break;
8568 case XPR_OP:
8569 ret = exprNode_op (exprNode_effect (exprData_getOpA (data)),
8570 exprNode_effect (exprData_getOpB (data)),
8571 exprData_getOpTok (data));
8572 break;
8573
8574 case XPR_POSTOP:
8575 ret = exprNode_postOp (exprNode_effect (exprData_getUopNode (data)),
8576 exprData_getUopTok (data));
8577 break;
8578 case XPR_PREOP:
8579 ret = exprNode_preOp (exprNode_effect (exprData_getUopNode (data)),
8580 exprData_getUopTok (data));
8581 break;
8582
8583 case XPR_OFFSETOF:
8584 case XPR_SIZEOFT:
8585 case XPR_SIZEOF:
8586 case XPR_ALIGNOFT:
8587 case XPR_ALIGNOF:
8588 ret = e;
8589 break;
8590
8591 case XPR_VAARG:
8592 ret = exprNode_vaArg (exprData_getCastTok (data),
8593 exprNode_effect (exprData_getCastNode (data)),
8594 exprData_getCastType (data));
8595 break;
8596
8597 case XPR_CAST:
8598 ret = exprNode_cast (exprData_getCastTok (data),
8599 exprNode_effect (exprData_getCastNode (data)),
8600 exprData_getCastType (data));
8601 break;
8602 case XPR_ITERCALL:
8603 ret = exprNode_iterStart (exprData_getIterCallIter (data),
8604 exprNodeList_effect
8605 (exprData_getIterCallArgs (data)));
8606 break;
8607
8608 case XPR_ITER:
8609 ret = exprNode_iter (exprData_getIterSname (data),
8610 exprNodeList_effect (exprData_getIterAlist (data)),
8611 exprNode_effect (exprData_getIterBody (data)),
8612 exprData_getIterEname (data));
8613 break;
8614
8615 case XPR_FOR:
8616 ret = exprNode_for (exprNode_effect (exprData_getPairA (data)),
8617 exprNode_effect (exprData_getPairB (data)));
8618 break;
8619
8620 case XPR_FORPRED:
8621 ret = exprNode_forPred (exprNode_effect (exprData_getTripleInit (data)),
8622 exprNode_effect (exprData_getTripleTest (data)),
8623 exprNode_effect (exprData_getTripleInc (data)));
8624 break;
8625
8626 case XPR_TOK:
8627 ret = exprNode_createTok (exprData_getTok (data));
8628 break;
8629
8630 case XPR_GOTO:
8631 ret = exprNode_goto (exprData_getLiteral (data));
8632 ret->loc = fileloc_update (ret->loc, e->loc);
8633 break;
8634
8635 case XPR_CONTINUE:
8636 ret = exprNode_continue (exprData_getTok (data), QSAFEBREAK);
8637 break;
8638
8639 case XPR_BREAK:
8640 ret = exprNode_break (exprData_getTok (data), QSAFEBREAK);
8641 break;
8642
8643 case XPR_RETURN:
8644 ret = exprNode_return (exprNode_effect (exprData_getSingle (data)));
8645 break;
8646
8647 case XPR_NULLRETURN:
8648 ret = exprNode_nullReturn (exprData_getTok (data));
8649 break;
8650
8651 case XPR_COMMA:
8652 ret = exprNode_comma (exprNode_effect (exprData_getPairA (data)),
8653 exprNode_effect (exprData_getPairB (data)));
8654 break;
8655
8656 case XPR_COND:
8657 ret = exprNode_cond (exprNode_effect (exprData_getTriplePred (data)),
8658 exprNode_effect (exprData_getTripleTrue (data)),
8659 exprNode_effect (exprData_getTripleFalse (data)));
8660 break;
8661 case XPR_IF:
8662 ret = exprNode_if (exprNode_effect (exprData_getPairA (data)),
8663 exprNode_effect (exprData_getPairB (data)));
8664 break;
8665
8666 case XPR_IFELSE:
8667 ret = exprNode_ifelse (exprNode_effect (exprData_getTriplePred (data)),
8668 exprNode_effect (exprData_getTripleTrue (data)),
8669 exprNode_effect (exprData_getTripleFalse (data)));
8670 break;
8671 case XPR_WHILEPRED:
8672 ret = exprNode_whilePred (exprData_getSingle (data));
8673 break;
8674
8675 case XPR_WHILE:
8676 ret = exprNode_while (exprNode_effect (exprData_getPairA (data)),
8677 exprNode_effect (exprData_getPairB (data)));
8678 break;
8679
8680 case XPR_DOWHILE:
8681 ret = exprNode_doWhile (exprNode_effect (exprData_getPairA (data)),
8682 exprNode_effect (exprData_getPairB (data)));
8683 break;
8684
8685 case XPR_BLOCK:
8686 ret = exprNode_makeBlock (exprNode_effect (exprData_getSingle (data)));
8687 break;
8688
8689 case XPR_STMT:
8690 ret = exprNode_statement (exprNode_effect (exprData_getUopNode (data)),
8691 exprData_getUopTok (data));
8692 break;
8693
8694 case XPR_STMTLIST:
8695 ret = exprNode_concat (exprNode_effect (exprData_getPairA (data)),
8696 exprNode_effect (exprData_getPairB (data)));
8697 break;
8698
8699 case XPR_FTCASE:
8700 case XPR_CASE:
8701 ret = exprNode_caseMarker
8702 (exprNode_effect (exprData_getSingle (data)),
8703 TRUE);
8704 break;
8705
8706 case XPR_FTDEFAULT:
8707 case XPR_DEFAULT:
8708 ret = exprNode_createTok (exprData_getTok (data));
8709 break;
8710
8711 case XPR_SWITCH:
8712 ret = exprNode_switch (exprNode_effect (exprData_getPairA (data)),
8713 exprNode_effect (exprData_getPairB (data)));
8714 break;
8715
8716 case XPR_INIT:
8717 ret = exprNode_makeInitialization
8718 (exprData_getInitId (data),
8719 exprNode_effect (exprData_getInitNode (data)));
8720 break;
8721
8722 case XPR_FACCESS:
28bf4b0b 8723 ret = exprNode_fieldAccessAux
8724 (exprNode_effect (exprData_getFieldNode (data)),
8725 exprNode_loc (exprData_getFieldNode (data)),
8726 cstring_copy (exprData_getFieldName (data)));
616915dd 8727 break;
8728
8729 case XPR_ARROW:
28bf4b0b 8730 ret = exprNode_arrowAccessAux
8731 (exprNode_effect (exprData_getFieldNode (data)),
8732 exprNode_loc (exprData_getFieldNode (data)),
8733 cstring_copy (exprData_getFieldName (data)));
616915dd 8734 break;
8735
8736 case XPR_STRINGLITERAL:
8737 ret = e;
8738 break;
8739
8740 case XPR_NUMLIT:
8741 ret = e;
8742 break;
8743
8744 case XPR_NODE:
8745 ret = e;
8746 break;
8747 /*@-branchstate@*/
8748 }
8749 /*@=branchstate@*/
8750 /*@=observertrans@*/
8751 /*@=exposetrans@*/
8752 /*@=dependenttrans@*/
8753 }
8754
8755 if (!innerEffect)
8756 {
8757 inEffect = FALSE;
8758 }
8759
8760 return ret;
8761}
8762
8763static /*@observer@*/ cstring exprNode_rootVarName (exprNode e)
8764{
8765 cstring ret;
8766 exprData data;
8767
8768 if (exprNode_isError (e))
8769 {
8770 return cstring_undefined;
8771 }
8772
8773 data = e->edata;
8774
8775 switch (e->kind)
8776 {
8777 case XPR_PARENS:
8778 ret = exprNode_rootVarName (exprData_getUopNode (data));
8779 break;
8780 case XPR_ASSIGN:
8781 ret = exprNode_rootVarName (exprData_getOpA (data));
8782 break;
8783 case XPR_CONST:
8784 case XPR_VAR:
8785 ret = exprData_getId (data);
8786 break;
8787 case XPR_LABEL:
8788 case XPR_TOK:
8789 case XPR_ITERCALL:
8790 case XPR_EMPTY:
8791 case XPR_CALL:
8792 case XPR_INITBLOCK:
8793 case XPR_BODY:
8794 case XPR_FETCH:
8795 case XPR_OP:
8796 case XPR_POSTOP:
8797 case XPR_PREOP:
8798 case XPR_OFFSETOF:
8799 case XPR_ALIGNOFT:
8800 case XPR_ALIGNOF:
8801 case XPR_SIZEOFT:
8802 case XPR_SIZEOF:
8803 case XPR_VAARG:
8804 case XPR_CAST:
8805 case XPR_ITER:
8806 case XPR_FOR:
8807 case XPR_FORPRED:
8808 case XPR_BREAK:
8809 case XPR_RETURN:
8810 case XPR_NULLRETURN:
8811 case XPR_COMMA:
8812 case XPR_COND:
8813 case XPR_IF:
8814 case XPR_IFELSE:
8815 case XPR_WHILE:
8816 case XPR_WHILEPRED:
8817 case XPR_DOWHILE:
8818 case XPR_GOTO:
8819 case XPR_CONTINUE:
8820 case XPR_FTDEFAULT:
8821 case XPR_DEFAULT:
8822 case XPR_SWITCH:
8823 case XPR_FTCASE:
8824 case XPR_CASE:
8825 case XPR_BLOCK:
8826 case XPR_STMT:
8827 case XPR_STMTLIST:
8828 case XPR_INIT:
8829 case XPR_FACCESS:
8830 case XPR_ARROW:
8831 case XPR_NODE:
8832 case XPR_NUMLIT:
8833 case XPR_STRINGLITERAL:
8834 ret = cstring_undefined;
8835 break;
8836 }
8837
8838 return ret;
8839}
8840
616915dd 8841static /*@only@*/ cstring exprNode_doUnparse (exprNode e)
8842{
8843 cstring ret;
8844 exprData data;
8845
8846 if (exprNode_isError (e))
8847 {
8848 static /*@only@*/ cstring error = cstring_undefined;
8849
8850 if (!cstring_isDefined (error))
8851 {
8852 error = cstring_makeLiteral ("<error>");
8853 }
8854
8855 return error;
8856 }
8857
8858 data = e->edata;
8859
8860 switch (e->kind)
8861 {
8862 case XPR_PARENS:
8863 ret = message ("(%s)", exprNode_unparse (exprData_getUopNode (e->edata)));
8864 break;
8865 case XPR_ASSIGN:
8866 ret = message ("%s %s %s",
8867 exprNode_unparse (exprData_getOpA (data)),
8868 lltok_unparse (exprData_getOpTok (data)),
8869 exprNode_unparse (exprData_getOpB (data)));
8870 break;
8871 case XPR_CALL:
8872 ret = message ("%s(%q)",
8873 exprNode_unparse (exprData_getFcn (data)),
8874 exprNodeList_unparse (exprData_getArgs (data)));
8875 break;
8876 case XPR_INITBLOCK:
8877 ret = message ("{ %q }", exprNodeList_unparse (exprData_getArgs (data)));
8878 break;
8879 case XPR_EMPTY:
8880 ret = cstring_undefined;
8881 break;
8882 case XPR_LABEL:
8883 ret = message ("%s:", exprData_getId (data));
8884 break;
8885 case XPR_CONST:
8886 case XPR_VAR:
8887 ret = cstring_copy (exprData_getId (data));
8888 break;
8889 case XPR_FETCH:
8890 ret = message ("%s[%s]", exprNode_unparse (exprData_getPairA (data)),
8891 exprNode_unparse (exprData_getPairB (data)));
8892 break;
8893 case XPR_BODY:
8894 ret = message ("<body>");
8895 break;
8896 case XPR_OP:
8897 ret = message ("%s %s %s",
8898 exprNode_unparse (exprData_getOpA (data)),
8899 lltok_unparse (exprData_getOpTok (data)),
8900 exprNode_unparse (exprData_getOpB (data)));
8901 break;
8902
8903 case XPR_PREOP:
8904 ret = message ("%s%s",
8905 lltok_unparse (exprData_getUopTok (data)),
8906 exprNode_unparse (exprData_getUopNode (data)));
8907 break;
8908
8909 case XPR_POSTOP:
8910 ret = message ("%s%s",
8911 exprNode_unparse (exprData_getUopNode (data)),
8912 lltok_unparse (exprData_getUopTok (data)));
8913 break;
8914
8915 case XPR_OFFSETOF:
8916 ret = message ("offsetof(%s,%q)",
8917 ctype_unparse (qtype_getType (exprData_getOffsetType (data))),
8918 cstringList_unparseSep (exprData_getOffsetName (data), cstring_makeLiteralTemp (".")));
8919 break;
8920
8921 case XPR_SIZEOFT:
8922 ret = message ("sizeof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
8923 break;
8924
8925 case XPR_SIZEOF:
8926 ret = message ("sizeof(%s)", exprNode_unparse (exprData_getSingle (data)));
8927 break;
8928
8929 case XPR_ALIGNOFT:
8930 ret = message ("alignof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
8931 break;
8932
8933 case XPR_ALIGNOF:
8934 ret = message ("alignof(%s)", exprNode_unparse (exprData_getSingle (data)));
8935 break;
8936
8937 case XPR_VAARG:
8938 ret = message ("va_arg(%s, %q)",
8939 exprNode_unparse (exprData_getCastNode (data)),
8940 qtype_unparse (exprData_getCastType (data)));
8941 break;
8942
8943 case XPR_ITERCALL:
8944 ret = message ("%q(%q)",
8945 uentry_getName (exprData_getIterCallIter (data)),
8946 exprNodeList_unparse (exprData_getIterCallArgs (data)));
8947 break;
8948 case XPR_ITER:
8949 ret = message ("%q(%q) %s %q",
8950 uentry_getName (exprData_getIterSname (data)),
8951 exprNodeList_unparse (exprData_getIterAlist (data)),
8952 exprNode_unparse (exprData_getIterBody (data)),
8953 uentry_getName (exprData_getIterEname (data)));
8954 break;
8955 case XPR_CAST:
8956 ret = message ("(%q)%s",
8957 qtype_unparse (exprData_getCastType (data)),
8958 exprNode_unparse (exprData_getCastNode (data)));
8959 break;
8960
8961 case XPR_FOR:
8962 ret = message ("%s %s",
8963 exprNode_unparse (exprData_getPairA (data)),
8964 exprNode_unparse (exprData_getPairB (data)));
8965 break;
8966
8967 case XPR_FORPRED:
8968 ret = message ("for (%s; %s; %s)",
8969 exprNode_unparse (exprData_getTripleInit (data)),
8970 exprNode_unparse (exprData_getTripleTest (data)),
8971 exprNode_unparse (exprData_getTripleInc (data)));
8972 break;
8973
8974 case XPR_GOTO:
8975 ret = message ("goto %s", exprData_getLiteral (data));
8976 break;
8977
8978 case XPR_CONTINUE:
8979 ret = cstring_makeLiteral ("continue");
8980 break;
8981
8982 case XPR_BREAK:
8983 ret = cstring_makeLiteral ("break");
8984 break;
8985
8986 case XPR_RETURN:
8987 ret = message ("return %s", exprNode_unparse (exprData_getSingle (data)));
8988 break;
8989
8990 case XPR_NULLRETURN:
8991 ret = cstring_makeLiteral ("return");
8992 break;
8993
8994 case XPR_COMMA:
8995 ret = message ("%s, %s",
8996 exprNode_unparse (exprData_getPairA (data)),
8997 exprNode_unparse (exprData_getPairB (data)));
8998 break;
8999
9000 case XPR_COND:
9001 ret = message ("%s ? %s : %s",
9002 exprNode_unparse (exprData_getTriplePred (data)),
9003 exprNode_unparse (exprData_getTripleTrue (data)),
9004 exprNode_unparse (exprData_getTripleFalse (data)));
9005 break;
9006 case XPR_IF:
9007 ret = message ("if (%s) %s",
9008 exprNode_unparse (exprData_getPairA (data)),
9009 exprNode_unparse (exprData_getPairB (data)));
9010 break;
9011
9012 case XPR_IFELSE:
9013 ret = message ("if (%s) %s else %s",
9014 exprNode_unparse (exprData_getTriplePred (data)),
9015 exprNode_unparse (exprData_getTripleTrue (data)),
9016 exprNode_unparse (exprData_getTripleFalse (data)));
9017 break;
9018 case XPR_WHILE:
9019 ret = message ("while (%s) %s",
9020 exprNode_unparse (exprData_getPairA (data)),
9021 exprNode_unparse (exprData_getPairB (data)));
9022 break;
9023
9024 case XPR_WHILEPRED:
9025 ret = cstring_copy (exprNode_unparse (exprData_getSingle (data)));
9026 break;
9027
9028 case XPR_TOK:
9029 ret = cstring_copy (lltok_unparse (exprData_getTok (data)));
9030 break;
9031
9032 case XPR_DOWHILE:
9033 ret = message ("do { %s } while (%s)",
9034 exprNode_unparse (exprData_getPairB (data)),
9035 exprNode_unparse (exprData_getPairA (data)));
9036 break;
9037
9038 case XPR_BLOCK:
9039 ret = message ("{ %s }", exprNode_unparseFirst (exprData_getSingle (data)));
9040 break;
9041
9042 case XPR_STMT:
9043 ret = cstring_copy (exprNode_unparse (exprData_getUopNode (data)));
9044 break;
9045
9046 case XPR_STMTLIST:
9047 ret = message ("%s; %s",
9048 exprNode_unparse (exprData_getPairA (data)),
9049 exprNode_unparse (exprData_getPairB (data)));
9050 break;
9051
9052 case XPR_FTDEFAULT:
9053 case XPR_DEFAULT:
9054 ret = cstring_makeLiteral ("default:");
9055 break;
9056
9057 case XPR_SWITCH:
9058 ret = message ("switch (%s) %s",
9059 exprNode_unparse (exprData_getPairA (data)),
9060 exprNode_unparse (exprData_getPairB (data)));
9061 break;
9062
9063 case XPR_FTCASE:
9064 case XPR_CASE:
9065 ret = message ("case %s:",
9066 exprNode_unparse (exprData_getSingle (data)));
9067 break;
9068
9069 case XPR_INIT:
28bf4b0b 9070 if (exprNode_isError (exprData_getInitNode (data)))
9071 {
9072 ret = message ("%q", idDecl_unparseC (exprData_getInitId (data)));
9073 }
9074 else
9075 {
9076 ret = message ("%q = %s",
9077 idDecl_unparseC (exprData_getInitId (data)),
9078 exprNode_unparse (exprData_getInitNode (data)));
9079 }
616915dd 9080 break;
9081
9082 case XPR_FACCESS:
9083 ret = message ("%s.%s",
9084 exprNode_unparse (exprData_getFieldNode (data)),
9085 exprData_getFieldName (data));
9086 break;
9087
9088 case XPR_ARROW:
9089 ret = message ("%s->%s",
9090 exprNode_unparse (exprData_getFieldNode (data)),
9091 exprData_getFieldName (data));
9092 break;
9093
9094 case XPR_STRINGLITERAL:
28bf4b0b 9095 ret = message ("\"%s\"", exprData_getLiteral (data));
616915dd 9096 break;
9097
9098 case XPR_NUMLIT:
9099 ret = cstring_copy (exprData_getLiteral (data));
9100 break;
9101
9102 case XPR_NODE:
9103 ret = cstring_makeLiteral ("<node>");
9104 break;
9105 }
9106
9107 return ret;
9108}
9109
28bf4b0b 9110bool
9111exprNode_isInitializer (exprNode e)
9112{
9113 return (exprNode_isDefined (e)
9114 && e->kind == XPR_INIT);
9115}
9116
616915dd 9117bool
9118exprNode_isCharLit (exprNode e)
9119{
9120 if (exprNode_isDefined (e))
9121 {
9122 return (multiVal_isChar (exprNode_getValue (e)));
9123 }
9124 else
9125 {
9126 return FALSE;
9127 }
9128}
9129
9130bool
9131exprNode_isNumLit (exprNode e)
9132{
9133 if (exprNode_isDefined (e))
9134 {
9135 return (multiVal_isInt (exprNode_getValue (e)));
9136 }
9137 else
9138 {
9139 return FALSE;
9140 }
9141}
9142
9143static bool
9144exprNode_isFalseConstant (exprNode e)
9145{
9146 if (exprNode_isDefined (e))
9147 {
9148 cstring s = exprNode_rootVarName (e);
9149
9150 if (cstring_equal (s, context_getFalseName ()))
9151 {
9152 return TRUE;
9153 }
9154 }
9155
9156 return FALSE;
9157}
9158
9159bool
9160exprNode_matchLiteral (ctype expected, exprNode e)
9161{
9162 if (exprNode_isDefined (e))
9163 {
9164 multiVal m = exprNode_getValue (e);
9165
9166 if (multiVal_isDefined (m))
9167 {
9168 if (multiVal_isInt (m))
9169 {
9170 long int val = multiVal_forceInt (m);
9171
9172 if (ctype_isDirectBool (ctype_realishType (expected)))
9173 {
9174 if (val == 0)
9175 {
9176 return FALSE; /* really?! return TRUE; allow use of 0 for FALSE */
9177 }
9178 else
9179 {
9180 return FALSE;
9181 }
9182 }
9183
9184 if (ctype_isRealInt (expected))
9185 {
9186 /*
9187 ** unsigned <- [ constant >= 0 is okay ]
9188 */
9189
9190 if (ctype_isUnsigned (expected))
9191 {
9192 if (val < 0)
9193 {
9194 return FALSE;
9195 }
9196 }
9197
9198 /*
9199 ** No checks on sizes of integers...maybe add
9200 ** these later.
9201 */
9202
9203 DPRINTF (("Here: %s => %s", exprNode_unparse (e), ctype_unparse (expected)));
9204 DPRINTF (("Type: %s / %s", ctype_unparse (exprNode_getType (e)),
9205 bool_unparse (ctype_isInt (exprNode_getType (e)))));
9206
9207 if (context_getFlag (FLG_NUMLITERAL)
9208 && (ctype_isRegularInt (exprNode_getType (e)) || val == 0)) {
9209 return TRUE;
9210 } else {
9211 if (val == 0) {
9212 return TRUE;
9213 } else {
9214 return FALSE; /* evs 2000-05-17: previously, always returned TRUE */
9215 }
9216 }
9217 }
9218 else if (ctype_isChar (expected))
9219 {
9220 return FALSE;
9221 }
9222 else if (ctype_isArrayPtr (expected))
9223 {
9224 return (val == 0);
9225 }
9226 else if (ctype_isAnyFloat (expected))
9227 {
9228 return (context_getFlag (FLG_NUMLITERAL));
9229 }
9230 else
9231 {
9232 return FALSE;
9233 }
9234 }
9235 else if (multiVal_isDouble (m))
9236 {
9237 if (ctype_isAnyFloat (expected))
9238 {
9239 return TRUE;
9240 }
9241 }
9242 else if (multiVal_isChar (m))
9243 {
9244 char val = multiVal_forceChar (m);
9245
9246 if (ctype_isChar (expected))
9247 {
9248 if (ctype_isUnsigned (expected) && ((int)val) < 0)
9249 {
9250 return FALSE;
9251 }
9252 else
9253 {
9254 return TRUE;
9255 }
9256 }
9257 }
9258 else
9259 {
9260 return FALSE;
9261 }
9262 }
9263 }
9264
9265 return FALSE;
9266}
9267
9268bool
9269exprNode_matchType (ctype expected, exprNode e)
9270{
9271 ctype actual;
9272
9273 if (!exprNode_isDefined (e)) return TRUE;
9274
9275 actual = ctype_realishType (exprNode_getType (e));
9276
9277 if (ctype_match (ctype_realishType (expected), actual))
9278 {
9279 return TRUE;
9280 }
9281
9282 llassert (!exprNode_isError (e));
9283 return (exprNode_matchLiteral (expected, e));
9284}
9285
9286static bool
9287exprNode_matchTypes (exprNode e1, exprNode e2)
9288{
9289 ctype t1;
9290 ctype t2;
9291
9292 if (!exprNode_isDefined (e1)) return TRUE;
9293 if (!exprNode_isDefined (e2)) return TRUE;
9294
9295 /*
9296 ** realish type --- keep bools, bools
9297 */
9298
9299 t1 = ctype_realishType (exprNode_getType (e1));
9300 t2 = ctype_realishType (exprNode_getType (e2));
9301
9302 if (ctype_match (t1, t2))
9303 {
9304 return TRUE;
9305 }
9306
9307 return (exprNode_matchLiteral (t1, e2) || exprNode_matchLiteral (t2, e1));
9308}
9309
9310/*
9311** pass e as ct
9312*/
9313
9314static bool
9315 exprNode_matchArgType (ctype ct, exprNode e)
9316{
9317 ctype et;
9318
9319 if (!exprNode_isDefined (e))
9320 {
9321 return TRUE;
9322 }
9323
9324 et = ctype_realType (exprNode_getType (e));
9325
9326 if (ctype_matchArg (ct, et)) return TRUE;
9327
9328 llassert (!exprNode_isError (e));
9329 return (exprNode_matchLiteral (ct, e));
9330}
9331
9332static /*@only@*/ exprNodeSList
9333 exprNode_flatten (/*@dependent@*/ exprNode e) /*@*/
9334{
9335 if (exprNode_isDefined (e))
9336 {
9337 if (e->kind == XPR_STMTLIST)
9338 {
9339 return (exprNodeSList_append
9340 (exprNode_flatten (exprData_getPairA (e->edata)),
9341 exprNode_flatten (exprData_getPairB (e->edata))));
9342 }
9343 else if (e->kind == XPR_BLOCK)
9344 {
9345 return (exprNode_flatten (exprData_getSingle (e->edata)));
9346 }
9347 else
9348 {
9349 return (exprNodeSList_singleton (e));
9350 }
9351 }
9352
9353 return exprNodeSList_new ();
9354}
9355
9356static /*@exposed@*/ exprNode
9357exprNode_lastStatement (/*@returned@*/ exprNode e)
9358{
9359 if (exprNode_isDefined (e))
9360 {
9361 if (e->kind == XPR_STMTLIST)
9362 {
9363 exprNode b = exprData_getPairB (e->edata);
9364
9365 if (exprNode_isDefined (b))
9366 {
9367 return exprNode_lastStatement (b);
9368 }
9369 else
9370 {
9371 return exprNode_lastStatement (exprData_getPairA (e->edata));
9372 }
9373 }
9374 else if (e->kind == XPR_BLOCK)
9375 {
9376 return (exprNode_lastStatement (exprData_getSingle (e->edata)));
9377 }
9378 else
9379 {
9380 return (e);
9381 }
9382 }
9383
9384 return exprNode_undefined;
9385}
9386
9387static /*@exposed@*/ exprNode
9388exprNode_firstStatement (/*@returned@*/ exprNode e)
9389{
9390 if (exprNode_isDefined (e))
9391 {
9392 if (e->kind == XPR_STMTLIST)
9393 {
9394 exprNode b = exprData_getPairA (e->edata);
9395
9396 if (exprNode_isDefined (b))
9397 {
9398 return exprNode_firstStatement (b);
9399 }
9400 else
9401 {
9402 return exprNode_firstStatement (exprData_getPairB (e->edata));
9403 }
9404 }
9405 else if (e->kind == XPR_BLOCK)
9406 {
9407 return (exprNode_firstStatement (exprData_getSingle (e->edata)));
9408 }
9409 else
9410 {
9411 return (e);
9412 }
9413 }
9414
9415 return exprNode_undefined;
9416}
9417
9418static void
9419exprNode_mergeUSs (exprNode res, exprNode other)
9420{
9421 if (exprNode_isDefined (res) && exprNode_isDefined (other))
9422 {
9423 res->msets = sRefSet_union (res->msets, other->msets);
9424 res->sets = sRefSet_union (res->sets, other->sets);
9425 res->uses = sRefSet_union (res->uses, other->uses);
9426 }
9427}
9428
9429static void
9430exprNode_mergeCondUSs (exprNode res, exprNode other1, exprNode other2)
9431{
9432 if (exprNode_isDefined (res))
9433 {
9434 if (exprNode_isDefined (other1))
9435 {
9436 res->sets = sRefSet_union (res->sets, other1->sets);
9437 res->msets = sRefSet_union (res->msets, other1->msets);
9438 res->uses = sRefSet_union (res->uses, other1->uses);
9439 }
9440 if (exprNode_isDefined (other2))
9441 {
9442 res->sets = sRefSet_union (res->sets, other2->sets);
9443 res->msets = sRefSet_union (res->msets, other2->msets);
9444 res->uses = sRefSet_union (res->uses, other2->uses);
9445 }
9446 }
9447}
9448
9449/*
9450** modifies e->uses
9451**
9452** Reports errors is s is not defined.
9453*/
9454
9455static void
28bf4b0b 9456exprNode_addUse (exprNode e, /*@exposed@*/ sRef s)
616915dd 9457{
9458 if (exprNode_isDefined (e))
9459 {
9460 e->uses = sRefSet_insert (e->uses, s);
9461 }
9462}
9463
9464void
28bf4b0b 9465exprNode_checkUse (exprNode e, /*@exposed@*/ sRef s, fileloc loc)
616915dd 9466{
9467 if (sRef_isKnown (s) && !sRef_isConst (s))
9468 {
9469 /*
9470 ** need to check all outer types are useable
9471 */
9472
9473 DPRINTF (("Check use: %s / %s",
9474 exprNode_unparse (e), sRef_unparse (s)));
28bf4b0b 9475
616915dd 9476 exprNode_addUse (e, s);
9477
9478 if (!context_inProtectVars ())
9479 {
9480 /*
9481 ** only report the deepest error
9482 */
9483
9484 sRef errorRef = sRef_undefined;
9485 sRef lastRef = sRef_undefined;
9486 bool deadRef = FALSE;
9487 bool unuseable = FALSE;
9488 bool errorMaybe = FALSE;
9489
9490 while (sRef_isValid (s) && sRef_isKnown (s))
9491 {
9492 ynm readable = sRef_isReadable (s);
9493
28bf4b0b 9494 DPRINTF (("Readable: %s / %s",
9495 sRef_unparseFull (s), ynm_unparse (readable)));
9496
616915dd 9497 if (!(ynm_toBoolStrict (readable)))
9498 {
9499 if (ynm_isMaybe (readable))
9500 {
9501 lastRef = errorRef;
9502 errorRef = s;
cd7d9b17 9503 DPRINTF (("Setting ERROR: %s", sRef_unparseFull (s)));
616915dd 9504 deadRef = sRef_isPossiblyDead (errorRef);
9505 unuseable = sRef_isUnuseable (errorRef);
9506 errorMaybe = TRUE;
9507 }
9508 else
9509 {
9510 lastRef = errorRef;
9511 errorRef = s;
9512 deadRef = sRef_isDead (errorRef);
9513 unuseable = sRef_isUnuseable (errorRef);
9514 errorMaybe = FALSE;
9515 }
9516
9517 if (!sRef_isPartial (s))
9518 {
cd7d9b17 9519 DPRINTF (("Defining! %s", sRef_unparseFull (s)));
616915dd 9520 sRef_setDefined (s, fileloc_undefined);
9521 }
9522 }
9523
9524 s = sRef_getBaseSafe (s);
9525 } /* end while */
9526
9527 if (sRef_isValid (errorRef))
9528 {
9529 if (sRef_isValid (lastRef) && sRef_isField (lastRef)
9530 && sRef_isPointer (errorRef))
9531 {
9532 errorRef = lastRef;
9533 }
9534
9535 if (deadRef)
9536 {
9537 if (sRef_isThroughArrayFetch (errorRef))
9538 {
9539 if (optgenerror
9540 (FLG_STRICTUSERELEASED,
9541 message ("%q %q may be used after being released",
9542 sRef_unparseKindNamePlain (errorRef),
9543 sRef_unparse (errorRef)),
9544 loc))
9545 {
9546 sRef_showRefKilled (errorRef);
9547
9548 if (sRef_isKept (errorRef))
9549 {
9550 sRef_clearAliasState (errorRef, loc);
9551 }
9552 }
9553 }
9554 else
9555 {
9556 DPRINTF (("HERE: %s", sRef_unparse (errorRef)));
9557
9558 if (optgenerror
9559 (FLG_USERELEASED,
9560 message ("%q %q %qused after being released",
9561 sRef_unparseKindNamePlain (errorRef),
9562 sRef_unparse (errorRef),
9563 cstring_makeLiteral (errorMaybe
9564 ? "may be " : "")),
9565 loc))
9566 {
9567 sRef_showRefKilled (errorRef);
9568
9569 if (sRef_isKept (errorRef))
9570 {
9571 sRef_clearAliasState (errorRef, loc);
9572 }
9573 }
9574 }
9575 }
9576 else if (unuseable)
9577 {
9578 if (optgenerror
9579 (FLG_USEDEF,
9580 message ("%q %q%qused in inconsistent state",
9581 sRef_unparseKindName (errorRef),
9582 sRef_unparseOpt (errorRef),
9583 cstring_makeLiteral (errorMaybe ? "may be " : "")),
9584 loc))
9585 {
9586 sRef_showStateInconsistent (errorRef);
9587 }
9588 }
9589 else
9590 {
28bf4b0b 9591 DPRINTF (("HERE: %s", sRef_unparseFull (errorRef)));
616915dd 9592
9593 voptgenerror
9594 (FLG_USEDEF,
9595 message ("%q %q%qused before definition",
9596 sRef_unparseKindName (errorRef),
9597 sRef_unparseOpt (errorRef),
9598 cstring_makeLiteral (errorMaybe ? "may be " : "")),
9599 loc);
cd7d9b17 9600
9601 DPRINTF (("Error: %s", sRef_unparseFull (errorRef)));
616915dd 9602 }
9603
9604 sRef_setDefined (errorRef, loc);
9605
9606 if (sRef_isAddress (errorRef))
9607 {
9608 sRef_setDefined (sRef_getRootBase (errorRef), loc);
9609 }
9610 } /* end is error */
9611 }
9612 }
9613
9614 setCodePoint ();
9615}
9616
9617static void
28bf4b0b 9618checkSafeUse (exprNode e, /*@exposed@*/ sRef s)
616915dd 9619{
9620 if (exprNode_isDefined (e) && sRef_isKnown (s))
9621 {
9622 e->uses = sRefSet_insert (e->uses, s);
9623 }
9624}
9625
9626static void
9627exprNode_checkSetAny (exprNode e, /*@dependent@*/ cstring name)
9628{
9629 if (exprNode_isDefined (e))
9630 {
9631 e->sets = sRefSet_insert (e->sets, sRef_makeUnconstrained (name));
9632 }
9633}
9634
9635void
28bf4b0b 9636exprNode_checkSet (exprNode e, /*@exposed@*/ sRef s)
616915dd 9637{
9638 sRef defines = sRef_undefined;
9639
9640 if (sRef_isValid (s) && !sRef_isNothing (s))
9641 {
9642 uentry ue = sRef_getBaseUentry (s);
9643
9644 if (uentry_isValid (ue))
9645 {
9646 uentry_setLset (ue);
9647 }
9648
9649 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
9650 {
9651 voptgenerror (FLG_USEDEF,
9652 message ("Attempt to set unuseable storage: %q",
9653 sRef_unparse (s)),
9654 exprNode_loc (e));
9655 }
9656
9657 if (sRef_isMeaningful (s))
9658 {
9659
9660 if (sRef_isDead (s))
9661 {
9662 sRef base = sRef_getBaseSafe (s);
9663
9664 if (sRef_isValid (base)
9665 && sRef_isDead (base))
9666 {
9667 sRef_setPartial (s, exprNode_loc (e));
9668 }
9669
9670 defines = s; /* okay - modifies for only param */
9671 }
9672 else if (sRef_isPartial (s))
9673 {
9674 sRef eref = exprNode_getSref (e);
9675
9676 if (!sRef_isPartial (eref))
9677 {
9678 /*
9679 ** should do something different here???
9680 */
9681
9682 sRef_setDefinedComplete (eref, exprNode_loc (e));
9683 }
9684 else
9685 {
9686 sRef_setPartialDefinedComplete (eref, exprNode_loc (e));
9687 }
9688
9689 if (sRef_isMeaningful (eref))
9690 {
9691 defines = eref;
9692 }
9693 else
9694 {
9695 defines = s;
9696 }
9697 }
9698 else if (sRef_isAllocated (s))
9699 {
9700 sRef eref = exprNode_getSref (e);
9701
9702
9703 if (!sRef_isAllocated (eref))
9704 {
9705 sRef_setDefinedComplete (eref, exprNode_loc (e));
9706 }
9707 else
9708 {
9709 sRef base = sRef_getBaseSafe (eref);
9710
9711 if (sRef_isValid (base))
9712 {
9713 sRef_setPdefined (base, exprNode_loc (e));
9714 }
9715 }
9716
9717 defines = s;
9718 }
9719 else
9720 {
9721 sRef_setDefinedNCComplete (s, exprNode_loc (e));
9722 defines = s;
9723 }
9724
9725 }
9726 else /* not meaningful...but still need to insert it */
9727 {
9728 defines = s;
9729 }
9730 }
9731
9732 if (exprNode_isDefined (e) && sRef_isValid (defines))
9733 {
9734 e->sets = sRefSet_insert (e->sets, defines);
9735 }
9736}
9737
9738void
28bf4b0b 9739exprNode_checkMSet (exprNode e, /*@exposed@*/ sRef s)
616915dd 9740{
9741 if (sRef_isValid (s) && !sRef_isNothing (s))
9742 {
9743 uentry ue = sRef_getBaseUentry (s);
9744
9745 if (uentry_isValid (ue))
9746 {
9747 uentry_setLset (ue);
9748 }
9749
9750 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
9751 {
9752 voptgenerror (FLG_USEDEF,
9753 message ("Attempt to set unuseable storage: %q", sRef_unparse (s)),
9754 exprNode_loc (e));
9755 }
9756
9757 if (sRef_isMeaningful (s))
9758 {
9759 sRef_setDefinedComplete (s, exprNode_loc (e));
9760 }
9761
9762 if (exprNode_isDefined (e))
9763 {
9764 e->msets = sRefSet_insert (e->msets, s);
9765 }
9766 }
9767}
9768
9769static void
9770checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode fcn, uentryList params, exprNodeList args)
9771{
9772 checkAnyCall (fcn, cstring_undefined, params, args,
9773 FALSE, sRefSet_undefined, FALSE, 0);
9774}
9775
9776static void
9777checkOneArg (uentry ucurrent, /*@notnull@*/ exprNode current,
9778 /*@dependent@*/ exprNode fcn, bool isSpec, int argno, int totargs)
9779{
9780 setCodePoint ();
9781
9782 if (uentry_isYield (ucurrent))
9783 {
9784 sRef_setDefined (exprNode_getSref (current), exprNode_loc (current));
9785 exprNode_checkSet (current, current->sref);
9786 }
9787 else
9788 {
9789 if (uentry_isSefParam (ucurrent))
9790 {
9791 sRefSet sets = current->sets;
9792 sRef ref = exprNode_getSref (current);
9793
9794 if (sRef_isMacroParamRef (ref))
9795 {
9796 uentry ue = sRef_getUentry (ref);
9797
9798 if (!uentry_isSefParam (ue))
9799 {
9800 voptgenerror
9801 (FLG_SEFPARAMS,
9802 message
9803 ("Parameter %d to %s is declared sef, but "
9804 "the argument is a macro parameter declared "
9805 "without sef: %s",
9806 argno, exprNode_unparse (fcn),
9807 exprNode_unparse (current)),
9808 exprNode_loc (current));
9809 }
9810 }
9811
9812 if (!sRefSet_isEmpty (sets))
9813 {
9814 sRefSet reported = sRefSet_undefined;
9815
9816 sRefSet_realElements (current->sets, el)
9817 {
9818 if (sRefSet_isSameNameMember (reported, el))
9819 {
9820 ; /* don't report again */
9821 }
9822 else
9823 {
9824 if (sRef_isUnconstrained (el))
9825 {
9826 voptgenerror
9827 (FLG_SEFUNSPEC,
9828 message
9829 ("Parameter %d to %s is declared sef, but "
9830 "the argument calls unconstrained function %s "
9831 "(no guarantee it will not modify something): %s",
9832 argno, exprNode_unparse (fcn),
9833 sRef_unconstrainedName (el),
9834 exprNode_unparse (current)),
9835 exprNode_loc (current));
9836 }
9837 else
9838 {
9839 voptgenerror
9840 (FLG_SEFPARAMS,
9841 message
9842 ("Parameter %d to %s is declared sef, but "
9843 "the argument may modify %q: %s",
9844 argno, exprNode_unparse (fcn),
9845 sRef_unparse (el),
9846 exprNode_unparse (current)),
9847 exprNode_loc (current));
9848 }
9849 }
9850 } end_sRefSet_realElements;
9851 }
9852 }
9853
9854 checkPassTransfer (current, ucurrent, isSpec, fcn, argno, totargs);
9855 exprNode_mergeUSs (fcn, current);
9856 }
9857}
9858
9859static void
9860 checkAnyCall (/*@dependent@*/ exprNode fcn,
9861 /*@dependent@*/ cstring fname,
9862 uentryList pn,
9863 exprNodeList args,
9864 bool hasMods, sRefSet mods,
9865 bool isSpec,
9866 int specialArgs)
9867{
9868 int paramno = 0;
9869 int nargs = exprNodeList_size (args);
9870
9871 setCodePoint ();
9872
9873 /*
9874 ** concat all args ud's to f, add each arg sref as a use unless
9875 ** it was specified as "out", in which case it is a def.
9876 */
9877
9878 uentryList_reset (pn);
9879
9880 /*
9881 ** aliasing checks:
9882 **
9883 ** if paramn is only or unique, no other arg may alias argn
9884 */
9885
9886 exprNodeList_elements (args, current)
9887 {
9888 paramno++;
9889
9890 if (exprNode_isDefined (current))
9891 {
9892 if ((!uentryList_isUndefined (pn) && !uentryList_isFinished (pn)))
9893 {
9894 uentry ucurrent = uentryList_current (pn);
9895
9896 if (specialArgs == 0
9897 || (paramno < specialArgs))
9898 {
28bf4b0b 9899 checkOneArg (ucurrent, current, fcn, isSpec, paramno, nargs);
616915dd 9900
9901 if (context_maybeSet (FLG_ALIASUNIQUE))
9902 {
9903 if (uentry_isOnly (ucurrent)
9904 || uentry_isUnique (ucurrent))
9905 {
9906 checkUniqueParams (fcn, current, args,
9907 paramno, ucurrent);
9908 }
9909 }
9910 }
9911 }
9912 else /* uentry is undefined */
9913 {
9914 if (specialArgs == 0)
9915 {
9916 exprNode_checkUseParam (current);
9917 }
9918
9919 exprNode_mergeUSs (fcn, current);
9920 }
9921 }
9922 uentryList_advanceSafe (pn);
9923 } end_exprNodeList_elements;
9924
9925 if (hasMods)
9926 {
9927 setCodePoint ();
9928
9929 sRefSet_allElements (mods, s)
9930 {
9931 sRef fb;
9932 sRef rb = sRef_getRootBase (s);
9933
28bf4b0b 9934 if (sRef_isFileOrGlobalScope (rb))
616915dd 9935 {
9936 context_usedGlobal (rb);
9937 }
9938
9939 fb = sRef_fixBaseParam (s, args);
9940
9941 if (!sRef_isMacroParamRef (fb))
9942 {
9943 if (sRef_isNothing (fb))
9944 {
9945 ;
9946 }
9947 else
9948 {
9949 if (sRef_isValid (fb))
9950 {
9951 uentry ue = sRef_getBaseUentry (s);
9952
9953 if (uentry_isValid (ue))
9954 {
9955 uentry_setLset (ue);
9956 }
9957 }
9958
9959 fcn->sets = sRefSet_insert (fcn->sets, fb);
9960 }
9961 }
9962 sRef_clearDerivedComplete (s);
9963 } end_sRefSet_allElements;
9964
9965 setCodePoint ();
9966 }
9967 else
9968 {
9969 if (context_hasMods ())
9970 {
9971 if (context_maybeSet (FLG_MODUNCON))
9972 {
9973 voptgenerror
9974 (FLG_MODUNCON,
9975 message ("Undetected modification possible "
9976 "from call to unconstrained function %s: %s",
9977 fname,
9978 exprNode_unparse (fcn)),
9979 exprNode_loc (fcn));
9980 }
9981 }
9982 else
9983 {
9984 if (context_maybeSet (FLG_MODUNCONNOMODS)
9985 && !(context_inIterDef () || context_inIterEnd ()))
9986 {
9987 voptgenerror
9988 (FLG_MODUNCONNOMODS,
9989 message ("Undetected modification possible "
9990 "from call to unconstrained function %s: %s",
9991 fname,
9992 exprNode_unparse (fcn)),
9993 exprNode_loc (fcn));
9994 }
9995 }
9996
9997 exprNode_checkSetAny (fcn, fname);
9998 }
9999}
10000
10001void exprNode_checkUseParam (exprNode current)
10002{
10003 if (exprNode_isDefined (current))
10004 {
10005 exprNode_checkUse (current, current->sref, current->loc);
10006 }
10007}
10008
10009static ctype
10010 checkNumerics (ctype tr1, ctype tr2, ctype te1, ctype te2,
10011 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10012 lltok op)
10013{
10014 ctype ret = tr1;
10015
10016 if (!ctype_match (tr1, tr2))
10017 {
10018 if ((ctype_isRealInt (tr1) || ctype_isReal (tr1)) &&
10019 (ctype_isRealInt (tr2) || ctype_isReal (tr2)))
10020 {
10021 ;
10022 }
10023 else
10024 {
10025 (void) gentypeerror
10026 (tr1, e1, tr2, e2,
10027 message ("Incompatible types for %s (%s, %s): %s %s %s",
10028 lltok_unparse (op),
10029 ctype_unparse (te1),
10030 ctype_unparse (te2),
10031 exprNode_unparse (e1), lltok_unparse (op),
10032 exprNode_unparse (e2)),
10033 e1->loc);
10034 }
10035 ret = ctype_unknown;
10036 }
10037 else
10038 {
10039 if (ctype_isForceRealNumeric (&tr1) && ctype_isForceRealNumeric (&tr2))
10040 {
10041 ret = ctype_resolveNumerics (tr1, tr2);
10042 }
10043 else if (!context_msgStrictOps ())
10044 {
10045 if (ctype_isPointer (tr1))
10046 {
10047 if (ctype_isPointer (tr2) && !exprNode_isNullValue (e2))
10048 {
10049 ret = ctype_int;
10050 }
10051 else if (ctype_isInt (tr2))
10052 {
10053 ret = te1;
10054 }
10055 else
10056 {
10057 ret = ctype_unknown;
10058 }
10059 }
10060 else if (ctype_isPointer (tr2))
10061 {
10062 if (ctype_isPointer (tr1))
10063 {
10064 ret = ctype_int;
10065 }
10066 else if (ctype_isInt (tr1))
10067 {
10068 ret = te2;
10069 }
10070 else
10071 {
10072 ret = ctype_unknown;
10073 }
10074 }
10075 else
10076 {
10077 ret = ctype_resolveNumerics (tr1, tr2);
10078 }
10079 }
10080 else
10081 {
10082 int opid = lltok_getTok (op);
10083 bool comparop = (opid == EQ_OP || opid == NE_OP
10084 || opid == TLT || opid == TGT
10085 || opid == LE_OP || opid == GE_OP);
10086
10087 if (!ctype_isNumeric (tr1) && !ctype_isNumeric (tr2))
10088 {
10089 if (comparop
10090 && ((ctype_isEnum (tr1) && ctype_isEnum (tr2))
10091 || (ctype_isBool (tr1) && ctype_isBool (tr2))
10092 || (ctype_isChar (tr1) && ctype_isChar (tr2))))
10093 {
10094 ; /* no error */
10095 }
10096 else
10097 {
10098 if (ctype_sameName (te1, te2))
10099 {
10100 voptgenerror
10101 (FLG_STRICTOPS,
10102 message ("Operands of %s are non-numeric (%t): %s %s %s",
10103 lltok_unparse (op), te1,
10104 exprNode_unparse (e1), lltok_unparse (op),
10105 exprNode_unparse (e2)),
10106 e1->loc);
10107 }
10108 else
10109 {
10110 voptgenerror
10111 (FLG_STRICTOPS,
10112 message ("Operands of %s are non-numerics (%t, %t): %s %s %s",
10113 lltok_unparse (op), te1, te2,
10114 exprNode_unparse (e1), lltok_unparse (op),
10115 exprNode_unparse (e2)),
10116 e1->loc);
10117 }
10118 }
10119 }
10120 else if (!ctype_isNumeric (tr1))
10121 {
10122 voptgenerror
10123 (FLG_STRICTOPS,
10124 message ("Right operand of %s is non-numeric (%t): %s %s %s",
10125 lltok_unparse (op), te1,
10126 exprNode_unparse (e1), lltok_unparse (op),
10127 exprNode_unparse (e2)),
10128 e1->loc);
10129 }
10130 else
10131 {
10132 if (!ctype_isNumeric (tr2))
10133 {
10134 voptgenerror
10135 (FLG_STRICTOPS,
10136 message ("Left operand of %s is non-numeric (%t): %s %s %s",
10137 lltok_unparse (op), te2,
10138 exprNode_unparse (e1), lltok_unparse (op),
10139 exprNode_unparse (e2)),
10140 e2->loc);
10141 }
10142 }
10143
10144 ret = ctype_unknown;
10145 }
10146 }
10147
10148 return ret;
10149}
10150
10151static void
10152abstractOpError (ctype tr1, ctype tr2, lltok op,
10153 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10154 fileloc loc1, fileloc loc2)
10155{
10156 if (ctype_isRealAbstract (tr1) && ctype_isRealAbstract (tr2))
10157 {
10158 if (ctype_match (tr1, tr2))
10159 {
10160 voptgenerror
10161 (FLG_ABSTRACT,
10162 message ("Operands of %s are abstract type (%t): %s %s %s",
10163 lltok_unparse (op), tr1,
10164 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10165 loc1);
10166 }
10167 else
10168 {
10169 voptgenerror
10170 (FLG_ABSTRACT,
10171 message ("Operands of %s are abstract types (%t, %t): %s %s %s",
10172 lltok_unparse (op), tr1, tr2,
10173 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10174 loc1);
10175 }
10176 }
10177 else if (ctype_isRealAbstract (tr1))
10178 {
10179 voptgenerror
10180 (FLG_ABSTRACT,
10181 message ("Left operand of %s is abstract type (%t): %s %s %s",
10182 lltok_unparse (op), tr1,
10183 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10184 loc1);
10185 }
10186 else
10187 {
10188 if (ctype_isRealAbstract (tr2))
10189 {
10190 voptgenerror
10191 (FLG_ABSTRACT,
10192 message ("Right operand of %s is abstract type (%t): %s %s %s",
10193 lltok_unparse (op), tr2,
10194 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10195 loc2);
10196 }
10197 }
10198}
10199
10200/*
10201** e1 <= e2
10202**
10203** requies e1 and e2 and not error exprNode's.
10204**
10205** Checks:
10206**
10207** If e1 is a component of an abstract type, and e2 is mutable and client-visible,
10208** the rep of the abstract type is exposed.
10209**
10210** The order is very important:
10211**
10212** check rep expose (move into check transfer)
10213** check transfer
10214** setup aliases
10215*/
10216
10217/*
10218** This isn't really a sensible procedure, but the indententation
10219** was getting too deep.
10220*/
10221
10222static void
10223checkOneRepExpose (sRef ysr, sRef base,
10224 /*@notnull@*/ exprNode e1,
10225 /*@notnull@*/ exprNode e2, ctype ct,
10226 sRef s2b)
10227{
10228 if (!(sRef_isOnly (ysr) || sRef_isKeep (ysr)
08eb3d0e 10229 || sRef_isOwned (ysr)
10230 || sRef_isExposed (ysr)))
616915dd 10231 {
08eb3d0e 10232 if (sRef_isAnyParam (base) && !sRef_isExposed (base)
10233 && !sRef_isObserver (base)) /* evans 2001-07-11: added isObserver */
10234
616915dd 10235 {
10236 if (sRef_isIReference (ysr))
10237 {
10238 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10239 {
10240 voptgenerror
10241 (FLG_ASSIGNEXPOSE,
10242 message
10243 ("Assignment of mutable component of parameter %q "
10244 "to component of abstract "
10245 "type %s exposes rep: %s = %s",
10246 sRef_unparse (base),
10247 ctype_unparse (ct),
10248 exprNode_unparse (e1), exprNode_unparse (e2)),
10249 e1->loc);
10250 }
10251 else
10252 {
10253 voptgenerror
10254 (FLG_ASSIGNEXPOSE,
10255 message
10256 ("Assignment of mutable component of parameter %q "
10257 "(through alias %q) to component of abstract "
10258 "type %s exposes rep: %s = %s",
10259 sRef_unparse (base),
10260 sRef_unparse (e2->sref),
10261 ctype_unparse (ct),
10262 exprNode_unparse (e1), exprNode_unparse (e2)),
10263 e1->loc);
10264 }
10265 }
10266 else
10267 {
10268 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10269 {
10270 voptgenerror
10271 (FLG_ASSIGNEXPOSE,
10272 message ("Assignment of mutable parameter %q "
10273 "to component of abstract type %s "
10274 "exposes rep: %s = %s",
10275 sRef_unparse (base),
10276 ctype_unparse (ct),
10277 exprNode_unparse (e1),
10278 exprNode_unparse (e2)),
10279 e1->loc);
10280 }
10281 else
10282 {
10283 voptgenerror
10284 (FLG_ASSIGNEXPOSE,
10285 message ("Assignment of mutable parameter %q "
10286 "(through alias %q) to "
10287 "component of abstract type %s exposes "
10288 "rep: %s = %s",
10289 sRef_unparse (base),
10290 sRef_unparse (e2->sref),
10291 ctype_unparse (ct),
10292 exprNode_unparse (e1),
10293 exprNode_unparse (e2)),
10294 e1->loc);
10295 }
10296 }
10297 }
10298
28bf4b0b 10299 if (sRef_isFileOrGlobalScope (s2b))
616915dd 10300 {
10301 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10302 {
10303 voptgenerror
10304 (FLG_REPEXPOSE,
10305 message ("Assignment of global %q "
10306 "to component of "
10307 "abstract type %s exposes rep: %s = %s",
10308 sRef_unparse (base),
10309 ctype_unparse (ct),
10310 exprNode_unparse (e1), exprNode_unparse (e2)),
10311 e1->loc);
10312 }
10313 else
10314 {
10315 voptgenerror
10316 (FLG_REPEXPOSE,
10317 message ("Assignment of global %q (through alias %q) "
10318 "to component of "
10319 "abstract type %s exposes rep: %s = %s",
10320 sRef_unparse (base),
10321 sRef_unparse (e2->sref),
10322 ctype_unparse (ct),
10323 exprNode_unparse (e1), exprNode_unparse (e2)),
10324 e1->loc);
10325 }
10326 }
10327 }
10328}
10329
10330static void
10331doAssign (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, bool isInit)
10332{
10333 if (ctype_isRealFunction (exprNode_getType (e1))
10334 && !ctype_isRealPointer (exprNode_getType (e1)))
10335 {
10336 voptgenerror
10337 (FLG_TYPE,
10338 message ("Invalid left-hand side of assignment (function type %s): %s",
10339 ctype_unparse (exprNode_getType (e1)),
10340 exprNode_unparse (e1)),
10341 e1->loc);
10342 }
10343
10344 if (context_getFlag (FLG_ASSIGNEXPOSE) && ctype_isMutable (e2->typ))
10345 {
10346 ctype t2 = exprNode_getType (e2);
10347 sRef sr = sRef_getRootBase (e1->sref);
10348 ctype ct = sRef_getType (sr);
10349
10350 if (ctype_isAbstract (t2)
10351 && !(uentry_isMutableDatatype (usymtab_getTypeEntry (ctype_typeId (t2)))))
10352 {
10353 /* it is immutable, okay to reference */
10354 goto donerepexpose;
10355 }
10356
10357 if (ctype_isAbstract (ct) && sRef_isIReference (e1->sref))
10358 {
10359 sRef s2b = sRef_getRootBase (e2->sref);
10360 sRef s1 = e1->sref;
10361 sRef s1b = sRef_getRootBase (s1);
10362 sRefSet aliases;
10363
10364 aliases = usymtab_canAlias (e2->sref);
10365
10366 if (!sRef_similar (s2b, s1b)
10367 && !sRef_isExposed (s1)
10368 && !(sRef_isOnly (s2b) || sRef_isKeep (s2b) || sRef_isExposed (s2b)))
10369 {
10370 if (sRef_isAnyParam (s2b) && !sRef_isOnly (s2b)
10371 && !sRef_isOwned (s2b) && !sRef_isKeep (s2b)
10372 && !sRef_isExposed (s2b))
10373 {
10374 if (sRef_isIReference (e2->sref))
10375 {
10376 voptgenerror
10377 (FLG_ASSIGNEXPOSE,
10378 message
10379 ("Assignment of mutable component of parameter %q "
10380 "to component of abstract type %s exposes rep: %s = %s",
10381 sRef_unparse (s2b),
10382 ctype_unparse (ct),
10383 exprNode_unparse (e1), exprNode_unparse (e2)),
10384 e1->loc);
10385 }
10386 else
10387 {
10388 voptgenerror
10389 (FLG_ASSIGNEXPOSE,
10390 message ("Assignment of mutable parameter %q to "
10391 "component of abstract type %s exposes rep: %s = %s",
10392 sRef_unparse (s2b),
10393 ctype_unparse (ct),
10394 exprNode_unparse (e1), exprNode_unparse (e2)),
10395 e1->loc);
10396 }
10397 }
10398
28bf4b0b 10399 if (sRef_isFileOrGlobalScope (s2b))
616915dd 10400 {
10401 voptgenerror
10402 (FLG_ASSIGNEXPOSE,
10403 message ("Assignment of global %q to component of "
10404 "abstract type %s exposes rep: %s = %s",
10405 sRef_unparse (s2b),
10406 ctype_unparse (ct),
10407 exprNode_unparse (e1), exprNode_unparse (e2)),
10408 e1->loc);
10409 }
10410
10411 sRefSet_realElements (aliases, ysr)
10412 {
10413 sRef base = sRef_getRootBase (ysr);
10414
10415 if (sRef_similar (ysr, s2b) || sRef_similar (s1b, base)
10416 || sRef_sameName (base, s1b))
10417 {
10418 ; /* error already reported or same sref */
10419 }
10420 else
10421 {
10422 checkOneRepExpose (ysr, base, e1, e2, ct, s2b);
10423 }
10424 } end_sRefSet_realElements;
10425 }
10426 sRefSet_free (aliases);
10427 }
10428 }
10429
10430 donerepexpose:
10431
10432 /*
10433 ** function variables don't really work...
10434 */
10435
10436 if (!ctype_isFunction (ctype_realType (e2->typ)))
10437 {
10438 if (isInit)
10439 {
28bf4b0b 10440 DPRINTF (("Check init: %s / %s",
10441 exprNode_unparse (e1), exprNode_unparse (e2)));
616915dd 10442 checkInitTransfer (e1, e2);
10443 }
10444 else
10445 {
10446 checkAssignTransfer (e1, e2);
10447 }
10448 }
10449 else
10450 {
10451 sRef fref = e2->sref;
10452
10453 sRef_setDefState (e1->sref, sRef_getDefState (fref), e1->loc);
10454 sRef_setNullState (e1->sref, sRef_getNullState (fref), e1->loc);
10455
10456 /* Need to typecheck the annotation on the parameters */
10457
10458 if (ctype_isRealFunction (e1->typ)) {
10459 uentryList e1p = ctype_argsFunction (ctype_realType (e1->typ));
10460 uentryList e2p = ctype_argsFunction (ctype_realType (e2->typ));
10461
10462 if (!uentryList_isMissingParams (e1p)
10463 && !uentryList_isMissingParams (e2p)
10464 && uentryList_size (e1p) > 0) {
10465 if (uentryList_size (e1p) == uentryList_size (e2p)) {
10466 int n = 0;
10467
10468 uentryList_elements (e1p, el1) {
10469 uentry el2;
10470
10471 el2 = uentryList_getN (e2p, n);
10472 n++;
10473 uentry_checkMatchParam (el1, el2, n, e2);
10474 } end_uentryList_elements;
10475 }
10476 }
10477 }
10478 }
10479
28bf4b0b 10480 if (isInit && sRef_isFileOrGlobalScope (e1->sref))
616915dd 10481 {
10482 ;
10483 }
10484 else
10485 {
28bf4b0b 10486 DPRINTF (("Update aliases: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
616915dd 10487 updateAliases (e1, e2);
10488 }
616915dd 10489}
10490
10491static void
10492checkMacroParen (exprNode e)
10493{
10494 if (exprNode_isError (e) || e->kind == XPR_CAST)
10495 {
10496 ;
10497 }
10498 else
10499 {
10500 if (sRef_isUnsafe (e->sref) && !exprNode_isInParens (e))
10501 {
10502 voptgenerror
10503 (FLG_MACROPARENS,
10504 message ("Macro parameter used without parentheses: %s",
10505 exprNode_unparse (e)),
10506 e->loc);
10507 }
10508 }
10509}
10510
10511static void
10512reflectNullTest (/*@notnull@*/ exprNode e, bool isnull)
10513{
10514 if (isnull)
10515 {
10516 e->guards = guardSet_addTrueGuard (e->guards, e->sref);
10517 }
10518 else
10519 {
10520 e->guards = guardSet_addFalseGuard (e->guards, e->sref);
10521 }
10522}
10523
10524/*
10525** e1 <= e2
10526**
10527** if e2 is a parameter or global derived location which
10528** can be modified (that is, e2 is a mutable abstract type,
10529** or a derived pointer), then e1 can alias e2.
10530**
10531** e1 can alias everything which e2 can alias.
10532**
10533** Also, if e1 is guarded, remove from guard sets!
10534*/
10535
10536static void updateAliases (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2)
10537{
10538 if (!context_inProtectVars ())
10539 {
10540 /*
10541 ** depends on types of e1 and e2
10542 */
10543
10544 sRef s1 = e1->sref;
10545 sRef s2 = e2->sref;
10546 ctype t1 = exprNode_getType (e1);
10547
10548 /* handle pointer sRefs, record fields, arrays, etc... */
10549
10550 if (!ctype_isRealSU (t1))
10551 {
28bf4b0b 10552 DPRINTF (("Copying real! %s", ctype_unparse (t1)));
616915dd 10553 sRef_copyRealDerivedComplete (s1, s2);
10554 }
28bf4b0b 10555 else
10556 {
10557 /*
10558 ** Fields should alias
10559 */
10560
10561 DPRINTF (("Not COPYING!: %s", ctype_unparse (t1)));
10562 }
616915dd 10563
10564 if (ctype_isMutable (t1) && sRef_isKnown (s1))
10565 {
10566 usymtab_clearAlias (s1);
10567 usymtab_addMustAlias (s1, s2);
28bf4b0b 10568 DPRINTF (("Add must alias: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
10569 }
10570 else
10571 {
10572 DPRINTF (("Not mutable: %s", ctype_unparse (t1)));
616915dd 10573 }
10574
10575 if (sRef_possiblyNull (s1) && usymtab_isGuarded (s1))
10576 {
10577 usymtab_unguard (s1);
10578 }
10579 }
10580}
10581
10582exprNode exprNode_updateLocation (/*@returned@*/ exprNode e, /*@temp@*/ fileloc loc)
10583{
10584 if (exprNode_isDefined (e))
10585 {
10586 e->loc = fileloc_update (e->loc, loc);
10587 }
10588 else
10589 {
10590 e = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
10591 }
10592
10593 return (e);
10594}
10595
10596static void checkUniqueParams (exprNode fcn,
10597 /*@notnull@*/ exprNode current,
10598 exprNodeList args,
10599 int paramno, uentry ucurrent)
10600{
10601 int iparamno = 0;
10602 sRef thisref = exprNode_getSref (current);
10603
10604 /*
10605 ** Check if any argument could match this argument.
10606 */
10607
10608 exprNodeList_elements (args, icurrent)
10609 {
10610 iparamno++;
10611
10612 if (iparamno != paramno)
10613 {
10614 sRef sr = exprNode_getSref (icurrent);
10615
10616 if (sRef_similarRelaxed (thisref, sr))
10617 {
10618 if (!sRef_isConst (thisref) && !sRef_isConst (sr))
10619 {
10620 voptgenerror
10621 (FLG_ALIASUNIQUE,
10622 message
10623 ("Parameter %d (%s) to function %s is declared %s but "
10624 "is aliased by parameter %d (%s)",
10625 paramno,
10626 exprNode_unparse (current),
10627 exprNode_unparse (fcn),
10628 alkind_unparse (uentry_getAliasKind (ucurrent)),
10629 iparamno, exprNode_unparse (icurrent)),
10630 current->loc);
10631 }
10632 }
10633 else
10634 {
10635 sRefSet aliases = usymtab_canAlias (sr);
10636
10637 sRefSet_allElements (aliases, asr)
10638 {
10639 if (ctype_isUnknown (sRef_getType (thisref)))
10640 {
10641 sRef_setType (thisref, uentry_getType (ucurrent));
10642 }
10643
10644 if (sRef_similarRelaxed (thisref, asr))
10645 {
10646 if (sRef_isExternal (asr))
10647 {
10648 if (sRef_isLocalState (thisref))
10649 {
10650 ; /* okay */
10651 }
10652 else
10653 {
10654 sRef base = sRef_getRootBase (asr);
10655
10656 if (!sRef_similar (sRef_getBase (asr), thisref))
10657 {
10658 if (sRef_isUnique (base) || sRef_isOnly (base)
10659 || sRef_isKept (base)
10660 || (sRef_isAddress (asr) && sRef_isLocalVar (base))
10661 || (sRef_isAddress (thisref)
10662 && sRef_isLocalVar (sRef_getRootBase (thisref))))
10663 {
10664 ; /* okay, no error */
10665 }
10666 else
10667 {
10668 voptgenerror
10669 (FLG_MAYALIASUNIQUE,
10670 message
10671 ("Parameter %d (%s) to function %s is declared %s but "
10672 "may be aliased externally by parameter %d (%s)",
10673 paramno,
10674 exprNode_unparse (current),
10675 exprNode_unparse (fcn),
10676 alkind_unparse (uentry_getAliasKind (ucurrent)),
10677 iparamno, exprNode_unparse (icurrent)),
10678 current->loc);
10679 }
10680 }
10681 }
10682 }
10683 else
10684 {
10685 voptgenerror
10686 (FLG_ALIASUNIQUE,
10687 message
10688 ("Parameter %d (%s) to function %s is declared %s but "
10689 "is aliased externally by parameter %d (%s) through "
10690 "alias %q",
10691 paramno,
10692 exprNode_unparse (current),
10693 exprNode_unparse (fcn),
10694 alkind_unparse (uentry_getAliasKind (ucurrent)),
10695 iparamno, exprNode_unparse (icurrent),
10696 sRef_unparse (asr)),
10697 current->loc);
10698 }
10699 }
10700 } end_sRefSet_allElements;
10701 sRefSet_free (aliases);
10702 }
10703 }
10704 } end_exprNodeList_elements;
10705}
10706
10707long exprNode_getLongValue (exprNode e) {
10708 long value;
10709
10710 if (exprNode_hasValue (e)
10711 && multiVal_isInt (exprNode_getValue (e)))
10712 {
10713 value = multiVal_forceInt (exprNode_getValue (e));
10714 }
10715 else
10716 {
10717 value = 0;
10718 }
10719
10720 return value;
10721}
10722
d46ce6a4 10723/*@observer@*/ fileloc exprNode_getfileloc (exprNode p_e)
616915dd 10724{
84c9ffbf 10725 if (exprNode_isDefined (p_e) )
d46ce6a4 10726 return ( p_e->loc );
616915dd 10727 else
10728 return fileloc_undefined;
10729}
10730
bb25bea6 10731/*@only@*/ fileloc exprNode_getNextSequencePoint (exprNode e)
616915dd 10732{
10733 /*
10734 ** Returns the location of the sequence point following e.
10735 **
10736 ** Only works for statements (for now).
10737 */
10738
10739 if (exprNode_isDefined (e) && e->kind == XPR_STMT) {
10740 lltok t = exprData_getUopTok (e->edata);
bb25bea6 10741 return fileloc_copy(lltok_getLoc (t));
616915dd 10742 } else {
28bf4b0b 10743 //drl possible problem : warning fix
616915dd 10744 // llcontbug (message ("Cannot get next sequence point: %s", exprNode_unparse (e)));
10745 return fileloc_undefined;
10746 }
10747 }
10748
9280addf 10749exprNode exprNode_createNew(ctype c)
10750{
10751 exprNode ret;
10752
10753 ret = exprNode_createPlain (c);
10754
10755 return ret;
10756}
d30bc0c7 10757
10758bool exprNode_isInitBlock (exprNode e)
10759{
10760 return (exprNode_isDefined(e) && e->kind == XPR_INITBLOCK);
10761}
This page took 1.517523 seconds and 5 git commands to generate.