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