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