00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 # include <ctype.h>
00029 # include "lclintMacros.nf"
00030 # include "basic.h"
00031 # include "cgrammar.h"
00032 # include "cgrammar_tokens.h"
00033
00034 # include "exprChecks.h"
00035 # include "aliasChecks.h"
00036 # include "exprNodeSList.h"
00037 # include "exprData.i"
00038
00039 static bool exprNode_isEmptyStatement (exprNode p_e);
00040 static exprNode exprNode_firstStatement ( exprNode p_e);
00041 static bool exprNode_isFalseConstant (exprNode p_e) ;
00042 static bool exprNode_isBlock (exprNode p_e);
00043 static void checkGlobUse (uentry p_glob, bool p_isCall, exprNode p_e);
00044 static void exprNode_addUse (exprNode p_e, sRef p_s);
00045 static bool exprNode_matchArgType (ctype p_ct, exprNode p_e);
00046 static exprNode exprNode_fakeCopy (exprNode p_e) ;
00047 static exprNode exprNode_statementError ( exprNode p_e);
00048 static bool exprNode_matchTypes (exprNode p_e1, exprNode p_e2);
00049 static void checkUniqueParams (exprNode p_fcn,
00050 exprNode p_current, exprNodeList p_args,
00051 int p_paramno, uentry p_ucurrent);
00052 static void updateAliases ( exprNode p_e1, exprNode p_e2);
00053 static void abstractOpError (ctype p_tr1, ctype p_tr2, lltok p_op,
00054 exprNode p_e1, exprNode p_e2,
00055 fileloc p_loc1, fileloc p_loc2);
00056 static ctype checkNumerics (ctype p_tr1, ctype p_tr2, ctype p_te1, ctype p_te2,
00057 exprNode p_e1, exprNode p_e2, lltok p_op);
00058 static void doAssign ( exprNode p_e1, exprNode p_e2, bool p_isInit);
00059 static void checkSafeUse (exprNode p_e, sRef p_s);
00060 static void reflectNullTest ( exprNode p_e, bool p_isnull);
00061 static void checkMacroParen (exprNode p_e);
00062 static exprNodeSList exprNode_flatten ( exprNode p_e);
00063 static void exprNode_checkSetAny (exprNode p_e, cstring p_name);
00064 static void exprNode_checkUse (exprNode p_e, sRef p_s, fileloc p_loc);
00065 static void exprNode_mergeUSs (exprNode p_res, exprNode p_other);
00066 static void exprNode_mergeCondUSs (exprNode p_res, exprNode p_other1, exprNode p_other2);
00067 static exprNode exprNode_fromIdentifierAux ( uentry p_c);
00068 static void checkAnyCall ( exprNode p_fcn,
00069 cstring p_fname,
00070 uentryList p_pn, exprNodeList p_args,
00071 bool p_hasMods, sRefSet p_mods, bool p_isSpec,
00072 int p_specialArgs);
00073 static void checkOneArg (uentry p_ucurrent, exprNode p_current,
00074 exprNode p_fcn, bool p_isSpec, int p_argno, int p_totargs);
00075 static void
00076 checkUnspecCall ( exprNode p_fcn, uentryList p_params, exprNodeList p_args);
00077
00078 static exprNode exprNode_effect (exprNode p_e)
00079 ;
00080 static cstring exprNode_doUnparse (exprNode p_e);
00081 static cstring exprNode_rootVarName (exprNode p_e);
00082 static exprNode
00083 exprNode_lastStatement ( exprNode p_e);
00084
00085 static sRef defref = sRef_undefined;
00086 static exprNode mustExitNode = exprNode_undefined;
00087
00088 static int checkArgsReal (uentry p_fcn, exprNode p_f,
00089 uentryList p_cl,
00090 exprNodeList p_args, bool p_isIter, exprNode p_ret);
00091
00092 static bool inEffect = FALSE;
00093 static int nowalloc = 0;
00094 static int totalloc = 0;
00095 static int maxalloc = 0;
00096
00097 static uentry regArg;
00098 static uentry outArg;
00099 static uentry outStringArg;
00100 static sRef stdinRef;
00101 static sRef stdoutRef;
00102 static uentry csArg;
00103 static uentry csOnlyArg;
00104 static ctype cstringType;
00105 static ctype ctypeType;
00106 static ctype filelocType;
00107 static bool initMod = FALSE;
00108
00109
00110
00111
00112
00113 void exprNode_initMod (void)
00114
00115
00116
00117 {
00118 uentry ue;
00119 idDecl tmp;
00120
00121 initMod = TRUE;
00122 cstringType = ctype_unknown;
00123 ctypeType = ctype_unknown;
00124 filelocType = ctype_unknown;
00125
00126 defref = sRef_undefined;
00127
00128 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
00129 {
00130 cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
00131 }
00132
00133 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
00134 {
00135 ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
00136 }
00137
00138 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
00139 {
00140 filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
00141 }
00142
00143 if (usymtab_existsGlob (cstring_makeLiteralTemp ("stdin")))
00144 {
00145 ue = usymtab_lookupGlob (cstring_makeLiteralTemp ("stdin"));
00146 }
00147 else
00148 {
00149 ue = uentry_makeVariable (cstring_makeLiteralTemp ("stdin"),
00150 ctype_unknown,
00151 fileloc_getBuiltin (),
00152 FALSE);
00153 uentry_setHasNameError (ue);
00154 ue = usymtab_supGlobalEntryReturn (ue);
00155 }
00156
00157 stdinRef = sRef_makePointer (uentry_getSref (ue));
00158
00159 if (usymtab_existsGlob (cstring_makeLiteralTemp ("stdout")))
00160 {
00161 ue = usymtab_lookupGlob (cstring_makeLiteralTemp ("stdout"));
00162 }
00163 else
00164 {
00165 ue = uentry_makeVariable (cstring_makeLiteralTemp ("stdout"),
00166 ctype_unknown,
00167 fileloc_getBuiltin (),
00168 FALSE);
00169 uentry_setHasNameError (ue);
00170 ue = usymtab_supGlobalEntryReturn (ue);
00171 }
00172
00173 stdoutRef = sRef_makePointer (uentry_getSref (ue));
00174
00175 tmp = idDecl_create (cstring_undefined, qtype_create (ctype_unknown));
00176
00177 regArg = uentry_makeParam (tmp, PARAMUNKNOWN);
00178
00179 idDecl_setTyp (tmp,
00180 qtype_addQual (qtype_create (ctype_makePointer (ctype_unknown)),
00181 qual_createOut ()));
00182
00183 outArg = uentry_makeParam (tmp, PARAMUNKNOWN);
00184
00185 idDecl_setTyp (tmp, qtype_addQual (qtype_create (ctype_string),
00186 qual_createOut ()));
00187
00188 outStringArg = uentry_makeParam (tmp, PARAMUNKNOWN);
00189
00190 idDecl_setTyp (tmp, qtype_addQual (qtype_addQual (qtype_create (cstringType),
00191 qual_createOnly ()),
00192 qual_createNull ()));
00193
00194 csOnlyArg = uentry_makeParam (tmp, PARAMUNKNOWN);
00195
00196 idDecl_setTyp (tmp, qtype_addQual (qtype_create (cstringType), qual_createNull ()));
00197 csArg = uentry_makeParam (tmp, PARAMUNKNOWN);
00198
00199 idDecl_free (tmp);
00200 }
00201
00202 void
00203 exprNode_destroyMod (void)
00204
00205
00206 {
00207 if (initMod)
00208 {
00209 uentry_free (regArg);
00210 uentry_free (outArg);
00211 uentry_free (outStringArg);
00212
00213 exprNode_free (mustExitNode);
00214 initMod = FALSE;
00215
00216 }
00217
00218 }
00219
00220 static void exprNode_resetSref ( exprNode e)
00221 {
00222 e->sref = defref;
00223 }
00224
00225 static exprNode exprNode_fakeCopy (exprNode e)
00226 {
00227
00228 return e;
00229
00230 }
00231
00232 static bool isFlagKey (char key)
00233 {
00234 return (key == '-' || key == '+' || key == ' ' || key == '#');
00235 }
00236
00237 static void exprNode_combineControl ( exprNode ret,
00238 exprNode ifclause,
00239 exprNode elseclause)
00240 {
00241 ret->canBreak = ifclause->canBreak || elseclause->canBreak;
00242
00243 ret->mustBreak =
00244 (ifclause->mustBreak || exprNode_mustEscape (ifclause))
00245 && (elseclause->mustBreak || exprNode_mustEscape (elseclause));
00246
00247 ret->exitCode = exitkind_combine (ifclause->exitCode,
00248 elseclause->exitCode);
00249
00250 }
00251
00252
00253
00254
00255
00256 static bool shallowKind (exprKind kind)
00257 {
00258 return (kind == XPR_STRINGLITERAL
00259 || kind == XPR_NUMLIT
00260 || kind == XPR_EMPTY
00261 || kind == XPR_BODY
00262 || kind == XPR_NODE);
00263 }
00264
00265 static void
00266 exprNode_freeIniter ( exprNode e)
00267 {
00268 if (!exprNode_isError (e))
00269 {
00270 switch (e->kind)
00271 {
00272 case XPR_FACCESS:
00273 sfree (e->edata->field);
00274 sfree (e->edata);
00275 break;
00276 case XPR_FETCH:
00277 exprNode_free (e->edata->op->b);
00278 sfree (e->edata->op);
00279 sfree (e->edata);
00280 break;
00281 default:
00282 llbug (message ("other: %s", exprNode_unparse (e)));
00283 }
00284
00285 multiVal_free (e->val);
00286 cstring_free (e->etext);
00287 fileloc_free (e->loc);
00288 sRefSet_free (e->uses);
00289 sRefSet_free (e->sets);
00290 sRefSet_free (e->msets);
00291 guardSet_free (e->guards);
00292 sfree (e);
00293 }
00294 }
00295
00296 void
00297 exprNode_freeShallow ( exprNode e)
00298 {
00299 if (!exprNode_isError (e))
00300 {
00301 if (shallowKind (e->kind))
00302 {
00303 }
00304 else
00305 {
00306 if (!inEffect)
00307 {
00308 if (e->kind == XPR_EMPTY
00309 || e->kind == XPR_BODY
00310 || e->kind == XPR_STRINGLITERAL
00311 || e->kind == XPR_NUMLIT
00312 || e->kind == XPR_NODE
00313 || e->kind == XPR_OFFSETOF
00314 || e->kind == XPR_ALIGNOFT
00315 || e->kind == XPR_ALIGNOF
00316 || e->kind == XPR_SIZEOFT
00317 || e->kind == XPR_SIZEOF)
00318 {
00319
00320 }
00321 else
00322 {
00323
00324 cstring_free (e->etext);
00325 fileloc_free (e->loc);
00326 sRefSet_free (e->uses);
00327 sRefSet_free (e->sets);
00328 sRefSet_free (e->msets);
00329 guardSet_free (e->guards);
00330 exprData_freeShallow (e->edata, e->kind);
00331 nowalloc--;
00332 sfree (e);
00333
00334 }
00335 }
00336 }
00337 }
00338 }
00339
00340 void
00341 exprNode_free (exprNode e)
00342 {
00343 if (!exprNode_isError (e))
00344 {
00345 if (!inEffect)
00346 {
00347 multiVal_free (e->val);
00348 cstring_free (e->etext);
00349 fileloc_free (e->loc);
00350 sRefSet_free (e->uses);
00351 sRefSet_free (e->sets);
00352 sRefSet_free (e->msets);
00353 guardSet_free (e->guards);
00354 exprData_free (e->edata, e->kind);
00355
00356 nowalloc--;
00357 sfree (e);
00358
00359 }
00360 }
00361 }
00362
00363 exprNode
00364 exprNode_makeError ()
00365 {
00366 return exprNode_undefined;
00367 }
00368
00369 static exprNode
00370 exprNode_new (void)
00371 {
00372 exprNode ret = (exprNode) dmalloc (sizeof (*ret));
00373
00374
00375 nowalloc++;
00376 totalloc++;
00377
00378 if (nowalloc > maxalloc)
00379 {
00380 maxalloc = nowalloc;
00381 }
00382
00383 return ret;
00384 }
00385
00386 static exprNode
00387 exprNode_createPlain (ctype c)
00388
00389
00390
00391
00392 {
00393 exprNode e = exprNode_new ();
00394
00395 e->typ = c;
00396 e->kind = XPR_EMPTY;
00397 e->val = multiVal_undefined;
00398 e->sref = defref;
00399 e->etext = cstring_undefined;
00400 e->loc = fileloc_undefined;
00401 e->guards = guardSet_undefined;
00402 e->uses = sRefSet_undefined;
00403 e->sets = sRefSet_undefined;
00404 e->msets = sRefSet_undefined;
00405 e->edata = exprData_undefined;
00406 e->exitCode = XK_NEVERESCAPE;
00407 e->canBreak = FALSE;
00408 e->mustBreak = FALSE;
00409 e->isJumpPoint = FALSE;
00410 return (e);
00411 }
00412
00413 exprNode exprNode_makeMustExit (void)
00414 {
00415 if (exprNode_isUndefined (mustExitNode))
00416 {
00417 mustExitNode = exprNode_createPlain (ctype_unknown);
00418 mustExitNode->exitCode = XK_MUSTEXIT;
00419 }
00420
00421 return mustExitNode;
00422 }
00423
00424
00425 static exprNode exprNode_create (ctype c)
00426
00427
00428
00429
00430 {
00431 exprNode e = exprNode_createPlain (c);
00432 e->loc = fileloc_copy (g_currentloc);
00433 return (e);
00434 }
00435
00436 static exprNode exprNode_createUnknown (void)
00437
00438
00439
00440
00441 {
00442 return (exprNode_create (ctype_unknown));
00443 }
00444
00445 static exprNode
00446 exprNode_createLoc (ctype c, fileloc loc)
00447
00448
00449
00450
00451 {
00452 exprNode e = exprNode_createPlain (c);
00453 e->loc = loc;
00454 return (e);
00455 }
00456
00457 static void
00458 exprNode_copySets ( exprNode ret, exprNode e)
00459
00460 {
00461 if (exprNode_isDefined (e))
00462 {
00463 ret->guards = guardSet_copy (e->guards);
00464 ret->uses = sRefSet_newCopy (e->uses);
00465 ret->sets = sRefSet_newCopy (e->sets);
00466 ret->msets = sRefSet_newCopy (e->msets);
00467 }
00468 else
00469 {
00470 ret->guards = guardSet_undefined;
00471 ret->uses = sRefSet_undefined;
00472 ret->sets = sRefSet_undefined;
00473 ret->msets = sRefSet_undefined;
00474 }
00475 }
00476
00477 static exprNode
00478 exprNode_createPartialLocCopy (exprNode e, fileloc loc)
00479
00480
00481
00482 {
00483 exprNode ret = exprNode_new ();
00484
00485 if (exprNode_isError (e))
00486 {
00487 ret->typ = ctype_unknown;
00488 ret->val = multiVal_undefined;
00489 ret->loc = loc;
00490 ret->guards = guardSet_undefined;
00491 ret->uses = sRefSet_undefined;
00492 ret->sets = sRefSet_undefined;
00493 ret->msets = sRefSet_undefined;
00494 }
00495 else
00496 {
00497 ret->typ = e->typ;
00498 ret->val = multiVal_copy (e->val);
00499 ret->loc = loc;
00500 ret->guards = guardSet_copy (e->guards);
00501 ret->uses = sRefSet_newCopy (e->uses);
00502 ret->sets = sRefSet_newCopy (e->sets);
00503 ret->msets = sRefSet_newCopy (e->msets);
00504 }
00505
00506 ret->kind = XPR_EMPTY;
00507 ret->sref = defref;
00508 ret->etext = cstring_undefined;
00509 ret->exitCode = XK_NEVERESCAPE;
00510 ret->canBreak = FALSE;
00511 ret->mustBreak = FALSE;
00512 ret->isJumpPoint = FALSE;
00513 ret->edata = exprData_undefined;
00514
00515 return (ret);
00516 }
00517
00518
00519 static exprNode
00520 exprNode_createPartialCopy (exprNode e)
00521
00522
00523
00524 {
00525 return (exprNode_createPartialLocCopy (e, fileloc_copy (exprNode_loc (e))));
00526 }
00527
00528 static exprNode
00529 exprNode_createPartialNVCopy (exprNode e)
00530
00531
00532
00533 {
00534 exprNode ret = exprNode_new ();
00535
00536 if (exprNode_isError (e))
00537 {
00538 ret->typ = ctype_unknown;
00539 ret->loc = fileloc_undefined;
00540 ret->guards = guardSet_undefined;
00541 ret->uses = sRefSet_undefined;
00542 ret->sets = sRefSet_undefined;
00543 ret->msets = sRefSet_undefined;
00544 }
00545 else
00546 {
00547 ret->typ = e->typ;
00548 ret->loc = fileloc_copy (e->loc);
00549 ret->guards = guardSet_copy (e->guards);
00550 ret->uses = sRefSet_newCopy (e->uses);
00551 ret->sets = sRefSet_newCopy (e->sets);
00552 ret->msets = sRefSet_newCopy (e->msets);
00553 }
00554
00555 ret->val = multiVal_undefined;
00556 ret->kind = XPR_EMPTY;
00557 ret->sref = defref;
00558 ret->etext = cstring_undefined;
00559 ret->exitCode = XK_NEVERESCAPE;
00560 ret->canBreak = FALSE;
00561 ret->mustBreak = FALSE;
00562 ret->isJumpPoint = FALSE;
00563 ret->edata = exprData_undefined;
00564
00565 return (ret);
00566 }
00567
00568 static exprNode
00569 exprNode_createSemiCopy (exprNode e)
00570
00571
00572
00573
00574 {
00575 if (exprNode_isError (e))
00576 {
00577 return exprNode_createPlain (ctype_unknown);
00578 }
00579 else
00580 {
00581 exprNode ret = exprNode_new ();
00582
00583 ret->typ = e->typ;
00584 ret->val = multiVal_copy (e->val);
00585 ret->loc = fileloc_copy (e->loc);
00586 ret->guards = guardSet_undefined;
00587 ret->uses = sRefSet_undefined;
00588 ret->sets = sRefSet_undefined;
00589 ret->msets = sRefSet_undefined;
00590
00591 ret->kind = XPR_EMPTY;
00592 ret->sref = defref;
00593 ret->etext = cstring_undefined;
00594 ret->exitCode = XK_NEVERESCAPE;
00595 ret->canBreak = FALSE;
00596 ret->mustBreak = FALSE;
00597 ret->isJumpPoint = FALSE;
00598 ret->edata = exprData_undefined;
00599
00600 return (ret);
00601 }
00602 }
00603
00604 bool
00605 exprNode_isNullValue (exprNode e)
00606 {
00607 if (exprNode_isDefined (e))
00608 {
00609 multiVal m = exprNode_getValue (e);
00610
00611 if (multiVal_isInt (m))
00612 {
00613 return (multiVal_forceInt (m) == 0);
00614 }
00615 }
00616
00617 return FALSE;
00618 }
00619
00620 static bool
00621 exprNode_isUnknownConstant ( exprNode e)
00622 {
00623 while (e->kind == XPR_PARENS)
00624 {
00625 e = exprData_getUopNode (e->edata);
00626 llassert (exprNode_isDefined (e));
00627 }
00628
00629 if (e->kind == XPR_CONST)
00630 {
00631 multiVal m = exprNode_getValue (e);
00632
00633 if (multiVal_isUnknown (m))
00634 {
00635 return TRUE;
00636 }
00637 }
00638
00639 return FALSE;
00640 }
00641
00642 exprNode
00643 exprNode_numLiteral (ctype c, cstring t,
00644 fileloc loc, long val)
00645 {
00646 exprNode e = exprNode_createLoc (c, loc);
00647
00648 e->kind = XPR_NUMLIT;
00649
00650 llassert (multiVal_isUndefined (e->val));
00651 e->val = multiVal_makeInt (val);
00652 e->edata = exprData_makeLiteral (cstring_copy (t));
00653
00654 if (val == 0)
00655 {
00656 e->sref = sRef_makeUnknown ();
00657 sRef_setDefNull (e->sref, e->loc);
00658 }
00659
00660 DPRINTF (("Num lit: %s / %s", exprNode_unparse (e), ctype_unparse (exprNode_getType (e))));
00661 return (e);
00662 }
00663
00664 exprNode
00665 exprNode_charLiteral (char c, cstring text, fileloc loc)
00666 {
00667 exprNode e = exprNode_createLoc (ctype_char, loc);
00668
00669 if (context_getFlag (FLG_CHARINTLITERAL))
00670 {
00671 e->typ = ctype_makeConj (ctype_char, ctype_int);
00672 }
00673
00674 e->kind = XPR_NUMLIT;
00675 e->val = multiVal_makeChar (c);
00676
00677 e->edata = exprData_makeLiteral (cstring_copy (text));
00678 return (e);
00679 }
00680
00681 exprNode
00682 exprNode_floatLiteral (double d, ctype ct, cstring text, fileloc loc)
00683 {
00684 exprNode e = exprNode_createLoc (ct, loc);
00685
00686 e->kind = XPR_NUMLIT;
00687 e->val = multiVal_makeDouble (d);
00688 e->edata = exprData_makeLiteral (cstring_copy (text));
00689 return (e);
00690 }
00691
00692 multiVal exprNode_getValue (exprNode e)
00693 {
00694 while (exprNode_isInParens (e)) {
00695 if (e->edata != NULL) {
00696 e = exprData_getUopNode (e->edata);
00697 } else {
00698 break;
00699 }
00700 }
00701
00702 if (exprNode_isDefined (e)) {
00703 return e->val;
00704 } else {
00705 return multiVal_undefined;
00706 }
00707 }
00708
00709 exprNode
00710 exprNode_stringLiteral ( cstring t, fileloc loc)
00711 {
00712 exprNode e = exprNode_createLoc (ctype_string, loc);
00713 int len = cstring_length (t) - 2;
00714 char *ts = cstring_toCharsSafe (t);
00715 char *s = cstring_toCharsSafe (cstring_create (len + 1));
00716
00717 if (context_getFlag (FLG_STRINGLITERALLEN))
00718 {
00719 if (len > context_getValue (FLG_STRINGLITERALLEN))
00720 {
00721 voptgenerror (FLG_STRINGLITERALLEN,
00722 message
00723 ("String literal length (%d) exceeds maximum "
00724 "length (%d): %s",
00725 len,
00726 context_getValue (FLG_STRINGLITERALLEN),
00727 t),
00728 e->loc);
00729 }
00730 }
00731
00732 strncpy (s, ts+1, size_fromInt (len));
00733 *(s + len) = '\0';
00734
00735
00736 e->kind = XPR_STRINGLITERAL;
00737 e->val = multiVal_makeString (cstring_fromCharsO (s));
00738 e->edata = exprData_makeLiteral (t);
00739 e->sref = sRef_makeType (ctype_string);
00740
00741 if (context_getFlag (FLG_READONLYSTRINGS))
00742 {
00743 sRef_setAliasKind (e->sref, AK_STATIC, fileloc_undefined);
00744 sRef_setExKind (e->sref, XO_OBSERVER, loc);
00745 }
00746 else
00747 {
00748 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
00749 }
00750
00751 return (e);
00752 }
00753
00754 exprNode exprNode_fromUIO (cstring c)
00755 {
00756 fileloc loc = context_getSaveLocation ();
00757 exprNode e = exprNode_createPlain (ctype_unknown);
00758
00759 e->kind = XPR_VAR;
00760
00761 if (fileloc_isUndefined (loc))
00762 {
00763 loc = fileloc_copy (g_currentloc);
00764 }
00765
00766 e->loc = loc;
00767 e->sref = defref;
00768
00769 if (usymtab_exists (c))
00770 {
00771 uentry ue = usymtab_lookupEither (c);
00772
00773 if (uentry_isDatatype (ue)
00774 && uentry_isSpecified (ue))
00775 {
00776 llfatalerror
00777 (message ("%q: Specified datatype %s used in code, but not defined. "
00778 "(Cannot continue reasonably from this error.)",
00779 fileloc_unparse (e->loc), c));
00780 }
00781 else
00782 {
00783 BADBRANCH;
00784 }
00785 }
00786
00787 llassertprint (!usymtab_exists (c), ("Entry exists: %s", c));
00788
00789
00790
00791
00792
00793 if (!context_inIterEnd ())
00794 {
00795 if (context_inMacro ())
00796 {
00797 if (context_getFlag (FLG_UNRECOG))
00798 {
00799 voptgenerror
00800 (FLG_MACROUNDEF,
00801 message ("Unrecognized identifier in macro definition: %s", c), e->loc);
00802 }
00803 else
00804 {
00805 flagcode_recordSuppressed (FLG_UNRECOG);
00806 }
00807 }
00808 else
00809 {
00810 voptgenerror
00811 (FLG_UNRECOG, message ("Unrecognized identifier: %s", c),
00812 e->loc);
00813 }
00814 }
00815
00816 e->edata = exprData_makeId (uentry_makeUnrecognized (c, fileloc_copy (loc)));
00817
00818
00819 sRef_setAliasKind (e->sref, AK_ERROR, loc);
00820
00821 return (e);
00822 }
00823
00824 exprNode exprNode_createId ( uentry c)
00825 {
00826 if (uentry_isValid (c))
00827 {
00828 exprNode e = exprNode_new ();
00829
00830 e->typ = uentry_getType (c);
00831
00832 if (uentry_isFunction (c)
00833 && !sRef_isLocalVar (uentry_getSref (c)))
00834 {
00835 e->sref = sRef_undefined;
00836 }
00837 else
00838 {
00839 e->sref = uentry_getSref (c);
00840 }
00841
00842 if (sRef_isStateUnknown (e->sref) && uentry_isNonLocal (c))
00843 {
00844 sRef_setDefined (e->sref, fileloc_undefined);
00845 }
00846
00847
00848
00849
00850
00851
00852 e->etext = cstring_undefined;
00853
00854 if (uentry_isEitherConstant (c))
00855 {
00856 e->kind = XPR_CONST;
00857 e->val = multiVal_copy (uentry_getConstantValue (c));
00858 }
00859 else
00860 {
00861 e->kind = XPR_VAR;
00862 e->val = multiVal_unknown ();
00863 }
00864
00865 e->edata = exprData_makeId (c);
00866 e->loc = context_getSaveLocation ();
00867
00868 if (fileloc_isUndefined (e->loc))
00869 {
00870 fileloc_free (e->loc);
00871 e->loc = fileloc_copy (g_currentloc);
00872 }
00873
00874 e->guards = guardSet_new ();
00875 e->sets = sRefSet_new ();
00876 e->msets = sRefSet_new ();
00877 e->uses = sRefSet_new ();
00878
00879
00880 e->exitCode = XK_NEVERESCAPE;
00881 e->isJumpPoint = FALSE;
00882 e->canBreak = FALSE;
00883 e->mustBreak = FALSE;
00884
00885 return e;
00886 }
00887 else
00888 {
00889 return exprNode_createUnknown ();
00890 }
00891 }
00892
00893 exprNode
00894 exprNode_fromIdentifier ( uentry c)
00895 {
00896 exprNode ret;
00897
00898 if (context_justPopped ())
00899 {
00900 uentry ce = usymtab_lookupSafe (LastIdentifier ());
00901
00902 if (uentry_isValid (ce))
00903 {
00904 c = ce;
00905 }
00906 else
00907 {
00908 llbuglit ("Looks like Aunt Millie forgot to walk to dog again.");
00909 }
00910 }
00911
00912 ret = exprNode_fromIdentifierAux (c);
00913
00914 return ret;
00915 }
00916
00917
00918 static exprNode
00919 exprNode_fromIdentifierAux ( uentry c)
00920 {
00921 exprNode e = exprNode_createId (c);
00922 sRef sr = e->sref;
00923
00924 uentry_setUsed (c, e->loc);
00925
00926 if (uentry_isVar (c) && sRef_isGlobal (sr))
00927 {
00928 checkGlobUse (c, FALSE, e);
00929 }
00930
00931 return (e);
00932 }
00933
00934 static bool
00935 exprNode_isZero (exprNode e)
00936 {
00937 if (exprNode_isDefined (e))
00938 {
00939 multiVal m = exprNode_getValue (e);
00940
00941 if (multiVal_isInt (m))
00942 {
00943 return (multiVal_forceInt (m) == 0);
00944 }
00945 }
00946
00947 return FALSE;
00948 }
00949
00950 static bool
00951 exprNode_isNonNegative (exprNode e)
00952 {
00953 if (exprNode_isDefined (e))
00954 {
00955 multiVal m = exprNode_getValue (e);
00956
00957 if (multiVal_isInt (m))
00958 {
00959 return (multiVal_forceInt (m) >= 0);
00960 }
00961 }
00962
00963 return FALSE;
00964 }
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975 exprNode
00976 exprNode_arrayFetch ( exprNode e1, exprNode e2)
00977 {
00978
00979
00980
00981
00982
00983 if (exprNode_isError (e1))
00984 {
00985 exprNode_free (e2);
00986 return (exprNode_makeError ());
00987 }
00988 else
00989 {
00990 exprNode arr;
00991 exprNode ind;
00992 ctype carr = exprNode_getType (e1);
00993 ctype crarr = ctype_realType (carr);
00994
00995
00996
00997
00998
00999
01000 if (!ctype_isRealArray (crarr)
01001 && ctype_isRealNumeric (crarr)
01002 && !exprNode_isError (e2)
01003 && ctype_isRealAP (exprNode_getType (e2)))
01004 {
01005 arr = e2;
01006 ind = e1;
01007
01008 carr = exprNode_getType (arr);
01009 crarr = ctype_realType (carr);
01010 }
01011 else
01012 {
01013 arr = e1;
01014 ind = e2;
01015 }
01016
01017 if (sRef_possiblyNull (arr->sref))
01018 {
01019 if (!usymtab_isGuarded (arr->sref))
01020 {
01021 if (optgenerror (FLG_NULLDEREF,
01022 message ("Index of %s pointer %q: %s",
01023 sRef_nullMessage (arr->sref),
01024 sRef_unparse (arr->sref),
01025 exprNode_unparse (arr)),
01026 arr->loc))
01027 {
01028 sRef_showNullInfo (arr->sref);
01029
01030
01031 sRef_setNullError (arr->sref);
01032 }
01033 }
01034 }
01035
01036 if (exprNode_isError (ind))
01037 {
01038 if ((ctype_isArrayPtr (crarr)
01039 && !ctype_isFunction (crarr))
01040 || ctype_isUnknown (carr))
01041 {
01042 exprNode ret = exprNode_createPartialCopy (arr);
01043
01044 if (ctype_isKnown (carr))
01045 {
01046 ret->typ = ctype_baseArrayPtr (crarr);
01047 }
01048 else
01049 {
01050 ret->typ = ctype_unknown;
01051 }
01052
01053 ret->sref = sRef_makeArrayFetch (arr->sref);
01054
01055 ret->kind = XPR_FETCH;
01056
01057
01058
01059
01060
01061
01062 ret->edata = exprData_makePair (arr, ind);
01063 checkSafeUse (ret, arr->sref);
01064 return (ret);
01065 }
01066 else
01067 {
01068 voptgenerror (FLG_TYPE,
01069 message ("Array fetch from non-array (%t): %s[%s]", carr,
01070 exprNode_unparse (e1), exprNode_unparse (e2)),
01071 arr->loc);
01072 exprNode_free (arr);
01073 return (exprNode_makeError ());
01074 }
01075 }
01076 else
01077 {
01078 if (!ctype_isForceRealInt (&(ind->typ)))
01079 {
01080 ctype rt = ctype_realType (ind->typ);
01081
01082 if (ctype_isChar (rt))
01083 {
01084 vnoptgenerror
01085 (FLG_CHARINDEX,
01086 message ("Array fetch using non-integer, %t: %s[%s]",
01087 ind->typ,
01088 exprNode_unparse (e1), exprNode_unparse (e2)),
01089 arr->loc);
01090 }
01091 else if (ctype_isEnum (rt))
01092 {
01093 vnoptgenerror
01094 (FLG_ENUMINDEX,
01095 message ("Array fetch using non-integer, %t: %s[%s]",
01096 ind->typ,
01097 exprNode_unparse (e1), exprNode_unparse (e2)),
01098 arr->loc);
01099 }
01100 else
01101 {
01102 voptgenerror
01103 (FLG_TYPE,
01104 message ("Array fetch using non-integer, %t: %s[%s]",
01105 ind->typ,
01106 exprNode_unparse (e1), exprNode_unparse (e2)),
01107 arr->loc);
01108 }
01109
01110 multiVal_free (ind->val);
01111 ind->val = multiVal_unknown ();
01112 }
01113
01114 if (ctype_isArrayPtr (crarr) && !ctype_isFunction (crarr))
01115 {
01116 exprNode ret = exprNode_createSemiCopy (arr);
01117 multiVal m = exprNode_getValue (ind);
01118
01119 ret->typ = ctype_baseArrayPtr (crarr);
01120 ret->kind = XPR_FETCH;
01121
01122 if (multiVal_isInt (m))
01123 {
01124 int i = (int) multiVal_forceInt (m);
01125
01126 if (sRef_isValid (arr->sref)) {
01127 ret->sref = sRef_makeArrayFetchKnown (arr->sref, i);
01128 } else {
01129 ret->sref = sRef_undefined;
01130 }
01131 }
01132 else
01133 {
01134 ret->sref = sRef_makeArrayFetch (arr->sref);
01135 }
01136
01137 ret->sets = sRefSet_realNewUnion (arr->sets, ind->sets);
01138 ret->msets = sRefSet_realNewUnion (arr->msets, ind->msets);
01139 ret->uses = sRefSet_realNewUnion (arr->uses, ind->uses);
01140
01141
01142 ret->edata = exprData_makePair (arr, ind);
01143
01144 exprNode_checkUse (ret, ind->sref, ind->loc);
01145 exprNode_checkUse (ret, arr->sref, arr->loc);
01146
01147 return (ret);
01148 }
01149 else
01150 {
01151 if (ctype_isUnknown (carr))
01152 {
01153 exprNode ret = exprNode_createPartialCopy (arr);
01154
01155 ret->kind = XPR_FETCH;
01156 ret->typ = ctype_unknown;
01157 ret->sets = sRefSet_union (ret->sets, ind->sets);
01158 ret->msets = sRefSet_union (ret->msets, ind->msets);
01159 ret->uses = sRefSet_union (ret->uses, ind->uses);
01160
01161
01162 ret->edata = exprData_makePair (arr, ind);
01163
01164 exprNode_checkUse (ret, ind->sref, ind->loc);
01165 exprNode_checkUse (ret, arr->sref, arr->loc);
01166 return (ret);
01167 }
01168 else
01169 {
01170 voptgenerror
01171 (FLG_TYPE,
01172 message ("Array fetch from non-array (%t): %s[%s]", carr,
01173 exprNode_unparse (e1), exprNode_unparse (e2)),
01174 arr->loc);
01175
01176 exprNode_free (arr);
01177 exprNode_free (ind);
01178
01179 return (exprNode_makeError ());
01180 }
01181 }
01182 }
01183 }
01184 BADEXIT;
01185 }
01186
01187
01188 static int
01189 checkArgs (uentry fcn, exprNode f, ctype t,
01190 exprNodeList args, exprNode ret)
01191 {
01192 return (checkArgsReal (fcn, f, ctype_argsFunction (t), args, FALSE, ret));
01193 }
01194
01195
01196
01197
01198
01199
01200
01201
01202 static void
01203 checkPrintfArgs ( exprNode f, uentry fcn,
01204 exprNodeList args, exprNode ret, int argno)
01205 {
01206
01207
01208
01209
01210 int i = argno;
01211 fileloc formatloc;
01212 int nargs = exprNodeList_size (args);
01213 uentryList params = uentry_getParams (fcn);
01214 exprNode a;
01215
01216
01217
01218
01219
01220 llassert (uentryList_size (params) == argno + 1);
01221 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
01222
01223 a = exprNodeList_getN (args, argno - 1);
01224 formatloc = fileloc_copy (exprNode_loc (a));
01225
01226 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
01227 && exprNode_knownStringValue (a))
01228 {
01229 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
01230 char *code = format;
01231 char *ocode = code;
01232
01233 nargs = exprNodeList_size (args);
01234
01235 while ((code = strchr (code, '%')) != NULL)
01236 {
01237 char *origcode = code;
01238 char key = *(++code);
01239 ctype modtype = ctype_int;
01240 bool modified = FALSE;
01241
01242 fileloc_addColumn (formatloc, code - ocode);
01243
01244
01245 while (isFlagKey (key))
01246 {
01247 key = *(++code);
01248 fileloc_incColumn (formatloc);
01249 }
01250
01251 if (key == 'm')
01252 {
01253 continue;
01254 }
01255
01256
01257 while (isdigit ((int) key) != 0)
01258 {
01259 key = *(++code);
01260 fileloc_incColumn (formatloc);
01261 }
01262
01263
01264 if (key == '.')
01265 {
01266 key = *(++code);
01267 fileloc_incColumn (formatloc);
01268
01269
01270
01271
01272
01273
01274
01275
01276 if (key == '*')
01277 {
01278 ;
01279 }
01280 else
01281 {
01282 while (isdigit ((int) key) != 0)
01283 {
01284 key = *(++code);
01285 fileloc_incColumn (formatloc);
01286 }
01287 }
01288 }
01289
01290 if (key == 'h')
01291 {
01292 modtype = ctype_sint;
01293 key = *(++code);
01294 fileloc_incColumn (formatloc);
01295 }
01296 else if (key == 'l' || key == 'L')
01297 {
01298 modtype = ctype_lint;
01299 key = *(++code);
01300 fileloc_incColumn (formatloc);
01301
01302 if (key == 'l' || key == 'L') {
01303 modtype = ctype_llint;
01304 key = *(++code);
01305 fileloc_incColumn (formatloc);
01306 }
01307 }
01308 else
01309 {
01310 ;
01311 }
01312
01313
01314 ++code;
01315 fileloc_incColumn (formatloc);
01316
01317 if (key != '%')
01318 {
01319 if (i >= nargs)
01320 {
01321 if (optgenerror
01322 (FLG_TYPE,
01323 message ("No argument corresponding to %q format "
01324 "code %d (%%%h): \"%s\"",
01325 uentry_getName (fcn),
01326 i, key,
01327 cstring_fromChars (format)),
01328 f->loc))
01329 {
01330 if (fileloc_isDefined (formatloc)
01331 && context_getFlag (FLG_SHOWCOL))
01332 {
01333 llgenindentmsg (cstring_makeLiteral ("Corresponding format code"),
01334 formatloc);
01335 }
01336 }
01337 i++;
01338 }
01339 else
01340 {
01341 a = exprNodeList_getN (args, i);
01342 i++;
01343
01344 if (!exprNode_isError (a))
01345 {
01346 ctype expecttype;
01347
01348 switch (key)
01349 {
01350 case '*':
01351 expecttype = ctype_int;
01352 *(--code) = '%';
01353 fileloc_subColumn (formatloc, 1);
01354 break;
01355 case 'u':
01356 case 'o':
01357 expecttype = ctype_combine (ctype_uint, modtype);
01358 break;
01359
01360 case 'i':
01361 case 'd':
01362 expecttype = ctype_combine (ctype_int, modtype);
01363 break;
01364
01365 case 'x':
01366 case 'X':
01367 expecttype = ctype_combine (ctype_uint, modtype);
01368 break;
01369
01370 case 'e':
01371 case 'E':
01372 case 'g':
01373 case 'G':
01374 case 'f':
01375 expecttype = ctype_combine (ctype_double, modtype);
01376 break;
01377
01378 case 'c':
01379 expecttype = ctype_makeConj (ctype_char, ctype_uchar);
01380 break;
01381
01382 case 's':
01383 expecttype = ctype_string;
01384 break;
01385 case '[':
01386
01387 while (((key = *(++code)) != ']')
01388 && (key != '\0'))
01389 {
01390 fileloc_incColumn (formatloc);
01391 }
01392
01393 if (key == '\0')
01394 {
01395 llfatalerrorLoc
01396 (message ("Bad character set format: %s",
01397 cstring_fromChars (origcode)));
01398 }
01399
01400 expecttype = ctype_string;
01401 break;
01402
01403 case 'p':
01404 expecttype = ctype_makePointer (ctype_void);
01405
01406 break;
01407
01408 case 'n':
01409 expecttype = ctype_combine (ctype_makePointer (ctype_int), modtype);
01410 modified = TRUE;
01411 uentry_setDefState (regArg, SS_ALLOCATED);
01412 break;
01413
01414 case 'm':
01415
01416
01417 break;
01418
01419
01420 default:
01421 expecttype = ctype_unknown;
01422
01423 voptgenerror
01424 (FLG_FORMATCODE,
01425 message ("Unrecognized format code: %s",
01426 cstring_fromChars (origcode)),
01427 fileloc_isDefined (formatloc)
01428 ? formatloc : g_currentloc);
01429
01430 break;
01431 }
01432
01433 if (!(exprNode_matchArgType (expecttype, a)))
01434 {
01435 if (ctype_isVoidPointer (expecttype)
01436 && ctype_isRealAbstract (a->typ)
01437 && (context_getFlag (FLG_ABSTVOIDP)))
01438 {
01439 ;
01440 }
01441 else
01442 {
01443 if (llgenformattypeerror
01444 (expecttype, exprNode_undefined,
01445 a->typ, a,
01446 message ("Format argument %d to %q (%%%h) expects "
01447 "%t gets %t: %s",
01448 i - argno,
01449 uentry_getName (fcn),
01450 key, expecttype,
01451 a->typ, exprNode_unparse (a)),
01452 a->loc))
01453 {
01454 if (fileloc_isDefined (formatloc)
01455 && context_getFlag (FLG_SHOWCOL))
01456 {
01457 llgenindentmsg
01458 (cstring_makeLiteral
01459 ("Corresponding format code"),
01460 formatloc);
01461 }
01462 }
01463 }
01464 }
01465
01466 uentry_setType (regArg, expecttype);
01467 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
01468
01469 if (ctype_equal (expecttype, ctype_string))
01470 {
01471 exprNode_checkUse (a, sRef_makePointer (a->sref), a->loc);
01472 }
01473
01474 uentry_setType (regArg, ctype_unknown);
01475 uentry_fixupSref (regArg);
01476
01477 if (modified)
01478 {
01479 exprNode_checkCallModifyVal (a->sref, args, f, ret);
01480 }
01481 }
01482 else
01483 {
01484 ;
01485 }
01486 }
01487 }
01488 ocode = code;
01489 }
01490
01491 if (i < nargs)
01492 {
01493 voptgenerror (FLG_TYPE,
01494 message ("Format string for %q has %d arg%p, given %d",
01495 uentry_getName (fcn), i - argno, nargs - argno),
01496 f->loc);
01497 }
01498 }
01499 else
01500 {
01501
01502 }
01503
01504 fileloc_free (formatloc);
01505 }
01506
01507 static void
01508 checkScanfArgs ( exprNode f, uentry fcn,
01509 exprNodeList args, exprNode ret, int argno)
01510 {
01511 int i = argno;
01512 fileloc formatloc;
01513 int nargs = exprNodeList_size (args);
01514 uentryList params = uentry_getParams (fcn);
01515 exprNode a;
01516
01517
01518
01519
01520
01521 llassert (uentryList_size (params) == argno + 1);
01522 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
01523
01524 a = exprNodeList_getN (args, argno - 1);
01525 formatloc = fileloc_copy (exprNode_loc (a));
01526
01527 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
01528 && exprNode_knownStringValue (a))
01529 {
01530 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
01531 char *code = format;
01532 char *ocode = code;
01533
01534 nargs = exprNodeList_size (args);
01535
01536 while ((code = strchr (code, '%')) != NULL)
01537 {
01538 char *origcode = code;
01539 char key = *(++code);
01540 ctype modtype = ctype_int;
01541 char modifier = '\0';
01542 bool modified = TRUE;
01543 bool ignore = FALSE;
01544
01545 fileloc_addColumn (formatloc, code - ocode);
01546
01547
01548
01549
01550
01551
01552
01553
01554 if (key == '*')
01555 {
01556 key = *(++code);
01557 modified = FALSE;
01558 ignore = TRUE;
01559 fileloc_incColumn (formatloc);
01560 }
01561
01562
01563 while (isdigit ((int) key) != 0)
01564 {
01565 key = *(++code);
01566 fileloc_incColumn (formatloc);
01567 }
01568
01569 if (key == 'h')
01570 {
01571 modtype = ctype_sint;
01572 key = *(++code);
01573 fileloc_incColumn (formatloc);
01574 }
01575 else if (key == 'l' || key == 'L')
01576 {
01577 modtype = ctype_lint;
01578 modifier = key;
01579
01580 key = *(++code);
01581 fileloc_incColumn (formatloc);
01582
01583 if (key == 'l' || key == 'L') {
01584 modtype = ctype_llint;
01585 key = *(++code);
01586 fileloc_incColumn (formatloc);
01587 }
01588 }
01589 else
01590 {
01591 ;
01592 }
01593
01594
01595 ++code;
01596 fileloc_incColumn (formatloc);
01597
01598 if (key != '%')
01599 {
01600 if (ignore)
01601 {
01602 ;
01603 }
01604 else
01605 {
01606 if (i >= nargs)
01607 {
01608 if (optgenerror
01609 (FLG_TYPE,
01610 message ("No argument corresponding to %q format "
01611 "code %d (%%%h): \"%s\"",
01612 uentry_getName (fcn),
01613 i, key,
01614 cstring_fromChars (format)),
01615 f->loc))
01616 {
01617 if (fileloc_isDefined (formatloc)
01618 && context_getFlag (FLG_SHOWCOL))
01619 {
01620 llgenindentmsg
01621 (cstring_makeLiteral ("Corresponding format code"),
01622 formatloc);
01623 }
01624 }
01625 i++;
01626 }
01627 else
01628 {
01629 a = exprNodeList_getN (args, i);
01630 i++;
01631
01632 if (!exprNode_isError (a))
01633 {
01634 ctype expecttype;
01635
01636 switch (key)
01637 {
01638 case '*':
01639 expecttype = ctype_makePointer (ctype_int);
01640 *(--code) = '%';
01641 fileloc_subColumn (formatloc, 1);
01642 break;
01643 case 'u':
01644 case 'o':
01645 expecttype = ctype_makePointer (ctype_combine (ctype_uint, modtype));
01646 break;
01647
01648 case 'i':
01649 case 'd':
01650 case 'x':
01651 case 'X':
01652 expecttype = ctype_makePointer (ctype_combine (ctype_int, modtype));
01653 break;
01654
01655 case 'e':
01656 case 'E':
01657 case 'g':
01658 case 'G':
01659 case 'f':
01660
01661
01662 if (modifier == 'l')
01663 {
01664 expecttype = ctype_makePointer (ctype_double);
01665 }
01666 else if (modifier == 'L')
01667 {
01668 expecttype = ctype_makePointer (ctype_ldouble);
01669 }
01670 else
01671 {
01672 llassert (modifier == '\0');
01673 expecttype = ctype_makePointer (ctype_float);
01674 }
01675 break;
01676
01677 case 'c':
01678 expecttype = ctype_makePointer (ctype_makeConj (ctype_char, ctype_uchar));
01679 break;
01680
01681 case 's':
01682 expecttype = ctype_string;
01683 break;
01684
01685 case '[':
01686
01687 while (((key = *(++code)) != ']')
01688 && (key != '\0'))
01689 {
01690 fileloc_incColumn (formatloc);
01691 }
01692
01693 if (key == '\0')
01694 {
01695 llfatalerrorLoc
01696 (message ("Bad character set format: %s",
01697 cstring_fromChars (origcode)));
01698 }
01699
01700 expecttype = ctype_string;
01701 break;
01702
01703 case 'p':
01704 expecttype = ctype_unknown;
01705
01706 break;
01707
01708 case 'n':
01709 expecttype = ctype_makePointer (ctype_int);
01710 break;
01711
01712 default:
01713 expecttype = ctype_unknown;
01714
01715 voptgenerror
01716 (FLG_FORMATCODE,
01717 message ("Unrecognized format code: %s",
01718 cstring_fromChars (origcode)),
01719 fileloc_isDefined (formatloc)
01720 ? formatloc : g_currentloc);
01721
01722 break;
01723 }
01724
01725 if (!(exprNode_matchArgType (expecttype, a)))
01726 {
01727 if (ctype_isVoidPointer (expecttype)
01728 && ctype_isRealAbstract (a->typ)
01729 && (context_getFlag (FLG_ABSTVOIDP)))
01730 {
01731 ;
01732 }
01733 else
01734 {
01735 if (modifier != '\0')
01736 {
01737 if (llgenformattypeerror
01738 (expecttype, exprNode_undefined,
01739 a->typ, a,
01740 message ("Format argument %d to %q (%%%h%h) expects "
01741 "%t gets %t: %s",
01742 i - argno,
01743 uentry_getName (fcn),
01744 modifier,
01745 key, expecttype,
01746 a->typ, exprNode_unparse (a)),
01747 a->loc))
01748 {
01749 if (fileloc_isDefined (formatloc)
01750 && context_getFlag (FLG_SHOWCOL))
01751 {
01752 llgenindentmsg
01753 (cstring_makeLiteral
01754 ("Corresponding format code"),
01755 formatloc);
01756 }
01757 }
01758
01759 }
01760 else
01761 {
01762 if (llgenformattypeerror
01763 (expecttype, exprNode_undefined,
01764 a->typ, a,
01765 message ("Format argument %d to %q (%%%h) expects "
01766 "%t gets %t: %s",
01767 i - argno,
01768 uentry_getName (fcn),
01769 key, expecttype,
01770 a->typ, exprNode_unparse (a)),
01771 a->loc))
01772 {
01773 if (fileloc_isDefined (formatloc)
01774 && context_getFlag (FLG_SHOWCOL))
01775 {
01776 llgenindentmsg
01777 (cstring_makeLiteral
01778 ("Corresponding format code"),
01779 formatloc);
01780 }
01781 }
01782 }
01783 }
01784 }
01785
01786 uentry_setType (outArg, expecttype);
01787 checkOneArg (outArg, a, f, FALSE, i+1, nargs);
01788 uentry_setType (outArg, ctype_unknown);
01789 uentry_fixupSref (outArg);
01790
01791 if (modified)
01792 {
01793 exprNode_checkCallModifyVal (a->sref, args, f, ret);
01794 }
01795 }
01796 else
01797 {
01798
01799 }
01800 }
01801 }
01802 }
01803 ocode = code;
01804 }
01805
01806 if (i < nargs)
01807 {
01808 voptgenerror (FLG_TYPE,
01809 message ("Format string for %q has %d arg%p, given %d",
01810 uentry_getName (fcn), i - argno, nargs - argno),
01811 f->loc);
01812 }
01813 }
01814 else
01815 {
01816
01817 }
01818
01819 fileloc_free (formatloc);
01820 }
01821
01822 static void
01823 checkMessageArgs ( exprNode f,
01824 uentry fcn,
01825 exprNodeList args,
01826 int argno)
01827 {
01828
01829
01830
01831
01832 int nargs = exprNodeList_size (args);
01833 int i = argno;
01834 fileloc formatloc;
01835 exprNode a;
01836
01837 a = exprNodeList_getN (args, argno - 1);
01838 formatloc = fileloc_copy (exprNode_loc (a));
01839
01840 if (ctype_isUnknown (cstringType)) {
01841 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
01842 {
01843 cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
01844 }
01845 }
01846
01847 if (ctype_isUnknown (ctypeType)) {
01848 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
01849 {
01850 ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
01851 }
01852 }
01853
01854 if (ctype_isUnknown (filelocType)) {
01855 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
01856 {
01857 filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
01858 }
01859 }
01860
01861 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
01862 && exprNode_knownStringValue (a))
01863 {
01864 cstring format = multiVal_forceString (exprNode_getValue (a));
01865 char *code = cstring_toCharsSafe (format);
01866 char *ocode = code;
01867
01868 nargs = exprNodeList_size (args);
01869
01870 while ((code = strchr (code, '%')) != NULL)
01871 {
01872 char *origcode = code;
01873 char key = *(++code);
01874 bool isOnly = FALSE;
01875
01876 fileloc_addColumn (formatloc, code - ocode);
01877
01878 while (key >= '0' && key <= '9')
01879 {
01880 key = *(++code);
01881 fileloc_incColumn (formatloc);
01882 }
01883
01884 ++code;
01885 fileloc_incColumn (formatloc);
01886
01887 if (key != '%')
01888 {
01889 if (key == 'p')
01890 {
01891 goto nextKey;
01892 }
01893
01894 if (i >= nargs)
01895 {
01896 voptgenerror
01897 (FLG_TYPE,
01898 message ("Message missing format arg %d (%%%h): \"%s\"",
01899 i + 1, key, format),
01900 f->loc);
01901 i++;
01902 }
01903 else
01904 {
01905 a = exprNodeList_getN (args, i);
01906 i++;
01907
01908 nextKey:
01909 if (!exprNode_isError (a))
01910 {
01911 ctype expecttype;
01912
01913
01914
01915 switch (key)
01916 {
01917 case 'c':
01918 case 'h':
01919 expecttype = ctype_char; break;
01920 case 's':
01921 expecttype = cstringType; break;
01922 case 'q':
01923 expecttype = cstringType; isOnly = TRUE; break;
01924 case 'x':
01925 expecttype = cstringType; isOnly = TRUE; break;
01926 case 'd': expecttype = ctype_int; break;
01927 case 'u': expecttype = ctype_uint; break;
01928 case 'w': expecttype = ctype_ulint; break;
01929 case 'f': expecttype = ctype_float; break;
01930 case 'b': expecttype = ctype_bool; break;
01931 case 't': expecttype = ctypeType; break;
01932 case 'l': expecttype = filelocType; break;
01933 case 'p':
01934 expecttype = ctype_int;
01935 break;
01936 case 'r': expecttype = ctype_bool; break;
01937 default:
01938 expecttype = ctype_unknown;
01939 voptgenerror
01940 (FLG_FORMATCODE,
01941 message ("Unrecognized format code: %s",
01942 cstring_fromChars (origcode)),
01943 fileloc_isDefined (formatloc)
01944 ? formatloc : g_currentloc);
01945 break;
01946 }
01947
01948
01949 if (!(exprNode_matchArgType (expecttype, a)))
01950 {
01951 if (ctype_isVoidPointer (expecttype)
01952 && ctype_isRealAbstract (a->typ)
01953 && (context_getFlag (FLG_ABSTVOIDP)))
01954 {
01955 ;
01956 }
01957 else
01958 {
01959 if (llgenformattypeerror
01960 (expecttype, exprNode_undefined,
01961 a->typ, a,
01962 message ("Format argument %d to %q (%%%h) expects "
01963 "%t gets %t: %s",
01964 i - argno,
01965 uentry_getName (fcn),
01966 key, expecttype,
01967 a->typ, exprNode_unparse (a)),
01968 a->loc))
01969 {
01970 if (fileloc_isDefined (formatloc)
01971 && context_getFlag (FLG_SHOWCOL))
01972 {
01973 llgenindentmsg
01974 (cstring_makeLiteral
01975 ("Corresponding format code"),
01976 formatloc);
01977 }
01978 }
01979 }
01980 }
01981
01982 if (ctype_equal (expecttype, cstringType))
01983 {
01984 if (isOnly)
01985 {
01986 checkOneArg (csOnlyArg, a, f, FALSE, i+1, nargs);
01987 uentry_fixupSref (csOnlyArg);
01988 }
01989 else
01990 {
01991 checkOneArg (csArg, a, f, FALSE, i+1, nargs);
01992 uentry_fixupSref (csArg);
01993 }
01994 }
01995 else
01996 {
01997 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
01998 uentry_fixupSref (regArg);
01999 }
02000 }
02001 }
02002 }
02003 }
02004
02005 if (i < nargs)
02006 {
02007 voptgenerror (FLG_TYPE,
02008 message ("Format string for %q has %d arg%p, given %d",
02009 uentry_getName (fcn), i - argno, nargs -argno),
02010 f->loc);
02011 }
02012 }
02013 else
02014 {
02015
02016 }
02017
02018 fileloc_free (formatloc);
02019 }
02020
02021 static void
02022 checkExpressionDefinedAux ( exprNode e1,
02023 exprNode e2,
02024 sRefSet sets1,
02025 sRefSet sets2,
02026 lltok op,
02027 flagcode flag)
02028 {
02029 bool hadUncon = FALSE;
02030
02031 if (sRef_isGlobal (sRef_getRootBase (e1->sref)) &&
02032 sRefSet_hasUnconstrained (sets2))
02033 {
02034 voptgenerror
02035 (FLG_EVALORDERUNCON,
02036 message
02037 ("Expression may have undefined behavior (%q used in right operand "
02038 "may set global variable %q used in left operand): %s %s %s",
02039 sRefSet_unparseUnconstrained (sets2),
02040 sRef_unparse (sRef_getRootBase (e1->sref)),
02041 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
02042 e2->loc);
02043 }
02044
02045 if (sRef_isGlobal (sRef_getRootBase (e2->sref)) &&
02046 sRefSet_hasUnconstrained (sets1))
02047 {
02048 voptgenerror
02049 (FLG_EVALORDERUNCON,
02050 message
02051 ("Expression has undefined behavior (%q used in left operand "
02052 "may set global variable %q used in right operand): %s %s %s",
02053 sRefSet_unparseUnconstrained (sets1),
02054 sRef_unparse (e2->sref),
02055 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
02056 e2->loc);
02057 }
02058
02059 sRefSet_realElements (e1->uses, sr)
02060 {
02061 if (sRef_isMeaningful (sr) && sRefSet_member (sets2, sr))
02062 {
02063 voptgenerror
02064 (FLG_EVALORDER,
02065 message
02066 ("Expression has undefined behavior (left operand uses %q, "
02067 "modified by right operand): %s %s %s",
02068 sRef_unparse (sr),
02069 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
02070 e2->loc);
02071 }
02072 } end_sRefSet_realElements;
02073
02074 sRefSet_realElements (sets1, sr)
02075 {
02076 if (sRef_isMeaningful (sr))
02077 {
02078 if (sRef_same (sr, e2->sref))
02079 {
02080 voptgenerror
02081 (flag,
02082 message
02083 ("Expression has undefined behavior (value of right operand "
02084 "modified by left operand): %s %s %s",
02085 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
02086 e2->loc);
02087 }
02088 else if (sRefSet_member (e2->uses, sr))
02089 {
02090 voptgenerror
02091 (flag,
02092 message
02093 ("Expression has undefined behavior (left operand modifies %q, "
02094 "used by right operand): %s %s %s",
02095 sRef_unparse (sr),
02096 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
02097 e2->loc);
02098 }
02099 else
02100 {
02101 if (sRefSet_member (sets2, sr))
02102 {
02103 if (sRef_isUnconstrained (sr))
02104 {
02105 if (hadUncon)
02106 {
02107 ;
02108 }
02109 else
02110 {
02111 hadUncon = optgenerror
02112 (FLG_EVALORDERUNCON,
02113 message
02114 ("Expression may have undefined behavior. Left operand "
02115 "calls %q; right operand calls %q. The unconstrained "
02116 "functions may modify global state used by "
02117 "the other operand): %s %s %s",
02118 sRefSet_unparseUnconstrained (sets1),
02119 sRefSet_unparseUnconstrained (sets2),
02120 exprNode_unparse (e1), lltok_unparse (op),
02121 exprNode_unparse (e2)),
02122 e2->loc);
02123 }
02124 }
02125 else
02126 {
02127 voptgenerror
02128 (flag,
02129 message
02130 ("Expression has undefined behavior (both "
02131 "operands modify %q): %s %s %s",
02132 sRef_unparse (sr),
02133 exprNode_unparse (e1),
02134 lltok_unparse (op), exprNode_unparse (e2)),
02135 e2->loc);
02136 }
02137 }
02138 }
02139 }
02140 } end_sRefSet_realElements;
02141 }
02142
02143 static void checkExpressionDefined (exprNode e1, exprNode e2, lltok op)
02144 {
02145 bool hasError = FALSE;
02146
02147 if (exprNode_isError (e1) || exprNode_isError (e2))
02148 {
02149 return;
02150 }
02151
02152 if (sRefSet_member (e2->sets, e1->sref))
02153 {
02154 if (e2->kind == XPR_CALL)
02155 {
02156 ;
02157 }
02158 else
02159 {
02160 hasError = optgenerror
02161 (FLG_EVALORDER,
02162 message ("Expression has undefined behavior "
02163 "(value of left operand is modified "
02164 "by right operand): %s %s %s",
02165 exprNode_unparse (e1), lltok_unparse (op),
02166 exprNode_unparse (e2)),
02167 e2->loc);
02168 }
02169 }
02170
02171 if (context_getFlag (FLG_EVALORDERUNCON))
02172 {
02173 if (sRefSet_member (e2->msets, e1->sref))
02174 {
02175 if (e2->kind == XPR_CALL)
02176 {
02177 ;
02178 }
02179 else
02180 {
02181 hasError = optgenerror
02182 (FLG_EVALORDER,
02183 message
02184 ("Expression has undefined behavior (value of left "
02185 "operand may be modified by right operand): %s %s %s",
02186 exprNode_unparse (e1), lltok_unparse (op),
02187 exprNode_unparse (e2)),
02188 e2->loc);
02189 }
02190 }
02191 }
02192
02193 if (!hasError)
02194 {
02195 checkExpressionDefinedAux (e1, e2, e1->sets, e2->sets, op, FLG_EVALORDER);
02196
02197 if (context_maybeSet (FLG_EVALORDERUNCON))
02198 {
02199 checkExpressionDefinedAux (e1, e2, e1->msets,
02200 e2->msets, op, FLG_EVALORDERUNCON);
02201 }
02202 }
02203 }
02204
02205 static void checkSequencing (exprNode p_f, exprNodeList p_args);
02206
02207 static int
02208 checkArgsReal (uentry fcn, exprNode f, uentryList cl,
02209 exprNodeList args, bool isIter, exprNode ret)
02210 {
02211 int special = 0;
02212
02213 if (!exprNode_isError (f))
02214 {
02215 if (!uentryList_isMissingParams (cl))
02216 {
02217 int nargs = exprNodeList_size (args);
02218 int expectargs = uentryList_size (cl);
02219 ctype last;
02220 int i = 0;
02221
02222 if (expectargs == 0)
02223 {
02224 if (nargs != 0)
02225 {
02226 if (isIter)
02227 {
02228 voptgenerror
02229 (FLG_TYPE,
02230 message ("Iter %q invoked with %d args, "
02231 "declared void",
02232 uentry_getName (fcn),
02233 nargs),
02234 f->loc);
02235 }
02236 else
02237 {
02238 voptgenerror
02239 (FLG_TYPE,
02240 message ("Function %s called with %d args, "
02241 "declared void",
02242 exprNode_unparse (f), nargs),
02243 f->loc);
02244 }
02245 }
02246 return special;
02247 }
02248
02249 last = uentry_getType (uentryList_getN (cl, expectargs - 1));
02250
02251 exprNodeList_reset (args);
02252
02253 uentryList_elements (cl, current)
02254 {
02255 ctype ct = uentry_getType (current);
02256 exprNode a;
02257
02258 if (ctype_isElips (ct))
02259 {
02260
02261
02262
02263
02264
02265
02266
02267 if (uentry_isPrintfLike (fcn))
02268 {
02269 checkPrintfArgs (f, fcn, args, ret, i);
02270 special = i;
02271 }
02272 else if (uentry_isScanfLike (fcn))
02273 {
02274 checkScanfArgs (f, fcn, args, ret, i);
02275 special = i;
02276 }
02277 else if (uentry_isMessageLike (fcn))
02278 {
02279 checkMessageArgs (f, fcn, args, i);
02280 special = i;
02281 }
02282 else
02283 {
02284 llassert (!uentry_isSpecialFunction (fcn));
02285 }
02286
02287 nargs = expectargs;
02288 break;
02289 }
02290 else
02291 {
02292 if (i >= nargs) break;
02293
02294 a = exprNodeList_current (args);
02295 exprNodeList_advance (args);
02296
02297 i++;
02298
02299 if (exprNode_isError (a))
02300 {
02301 ;
02302 }
02303 else
02304 {
02305
02306
02307
02308
02309
02310 f->guards = guardSet_union (f->guards, a->guards);
02311
02312 DPRINTF (("match arg: %s / %s", ctype_unparse (ct), ctype_unparse (a->typ)));
02313
02314 if (!(exprNode_matchArgType (ct, a)))
02315 {
02316 DPRINTF (("Args mismatch!"));
02317
02318 if (ctype_isVoidPointer (ct)
02319 && (ctype_isPointer (a->typ)
02320 && (ctype_isRealAbstract (ctype_baseArrayPtr (a->typ)))))
02321 {
02322 vnoptgenerror
02323 (FLG_ABSTVOIDP,
02324 message
02325 ("Pointer to abstract type (%t) used "
02326 "as void pointer "
02327 "(arg %d to %q): %s",
02328 a->typ, i,
02329 uentry_getName (fcn),
02330 exprNode_unparse (a)),
02331 a->loc);
02332 }
02333 else
02334 {
02335 if (isIter)
02336 {
02337 (void) gentypeerror
02338 (ct, exprNode_undefined,
02339 a->typ, a,
02340 message
02341 ("Iter %q expects arg %d to "
02342 "be %t gets %t: %s",
02343 uentry_getName (fcn),
02344 i, ct, a->typ, exprNode_unparse (a)),
02345 a->loc);
02346 }
02347 else
02348 {
02349 if (gentypeerror
02350 (ct,
02351 exprNode_undefined,
02352 a->typ,
02353 a,
02354 message
02355 ("Function %q expects arg %d to be %t gets %t: %s",
02356 uentry_getName (fcn),
02357 i, ct, a->typ, exprNode_unparse (a)),
02358 a->loc))
02359 {
02360 DPRINTF (("Types: %s / %s",
02361 ctype_unparse (ct),
02362 ctype_unparse (a->typ)));
02363 }
02364
02365
02366
02367
02368
02369
02370 if (ctype_isAbstract (a->typ))
02371 {
02372 sRef_setNullUnknown (exprNode_getSref (a), a->loc);
02373 }
02374 }
02375 }
02376 }
02377 }
02378 }
02379 } end_uentryList_elements ;
02380
02381
02382 if (expectargs != nargs)
02383 {
02384 if (ctype_isElips (last))
02385 {
02386 voptgenerror
02387 (FLG_TYPE,
02388 message ("Function %s called with %d args, expects at least %d",
02389 exprNode_unparse (f),
02390 nargs, expectargs - 1),
02391 f->loc);
02392 }
02393 else
02394 {
02395 if (isIter)
02396 {
02397 voptgenerror
02398 (FLG_TYPE,
02399 message ("Iter %q invoked with %d args, expects %d",
02400 uentry_getName (fcn), nargs, expectargs),
02401 f->loc);
02402 }
02403 else
02404 {
02405 voptgenerror
02406 (FLG_TYPE,
02407 message ("Function %s called with %d args, expects %d",
02408 exprNode_unparse (f),
02409 nargs, expectargs),
02410 f->loc);
02411 }
02412 }
02413 }
02414 }
02415 }
02416
02417 return special;
02418 }
02419
02420
02421
02422
02423
02424
02425
02426
02427 static void
02428 checkSequencingOne (exprNode f, exprNodeList args,
02429 exprNode el, int argno)
02430 {
02431
02432
02433
02434
02435 int checkloop;
02436 int numloops = context_maybeSet (FLG_EVALORDERUNCON) ? 2 : 1;
02437
02438 for (checkloop = 0; checkloop < numloops; checkloop++)
02439 {
02440 sRefSet thissets;
02441
02442 if (checkloop == 0)
02443 {
02444 thissets = el->sets;
02445 }
02446 else
02447 {
02448 llassert (checkloop == 1);
02449 thissets = el->msets;
02450 }
02451
02452 sRefSet_realElements (thissets, thisset)
02453 {
02454 int j;
02455
02456
02457 for (j = 0; j < args->nelements; j++)
02458 {
02459 exprNode jl = args->elements[j];
02460 int thisargno = j + 1;
02461
02462 if (thisargno != argno && exprNode_isDefined (jl))
02463 {
02464 sRefSet otheruses = jl->uses;
02465
02466 if (sRef_isGlobal (sRef_getRootBase (jl->sref)) &&
02467 sRefSet_hasUnconstrained (thissets))
02468 {
02469 voptgenerror
02470 (FLG_EVALORDERUNCON,
02471
02472 message
02473 ("%q used in argument %d may set "
02474 "global variable %q used by argument %d: %s(%q)",
02475 cstring_capitalizeFree (sRefSet_unparseUnconstrained (thissets)),
02476
02477 argno,
02478 sRef_unparse (sRef_getRootBase (jl->sref)),
02479 thisargno,
02480 exprNode_unparse (f), exprNodeList_unparse (args)),
02481 el->loc);
02482 }
02483
02484 if (sRefSet_member (otheruses, thisset))
02485 {
02486 if (sRef_isUnconstrained (thisset))
02487 {
02488 voptgenerror
02489 (FLG_EVALORDERUNCON,
02490 message
02491 ("Unconstrained functions used in arguments %d (%q) "
02492 "and %d (%s) may modify "
02493 "or use global state in undefined way: %s(%q)",
02494 argno,
02495 sRefSet_unparseUnconstrainedPlain (otheruses),
02496 thisargno,
02497 sRef_unconstrainedName (thisset),
02498 exprNode_unparse (f),
02499 exprNodeList_unparse (args)),
02500 el->loc);
02501 }
02502 else
02503 {
02504 voptgenerror
02505 (FLG_EVALORDER,
02506 message
02507 ("Argument %d modifies %q, used by argument %d "
02508 "(order of evaluation of actual parameters is "
02509 "undefined): %s(%q)",
02510 argno, sRef_unparse (thisset), thisargno,
02511 exprNode_unparse (f), exprNodeList_unparse (args)),
02512 el->loc);
02513 }
02514 }
02515 else
02516 {
02517 sRefSet othersets = jl->sets;
02518
02519 if (sRefSet_member (othersets, thisset))
02520 {
02521 if (sRef_isUnconstrained (thisset))
02522 {
02523 voptgenerror
02524 (FLG_EVALORDERUNCON,
02525 message
02526 ("Unconstrained functions used in "
02527 "arguments %d (%q) and %d (%s) may modify "
02528 "or use global state in undefined way: %s(%q)",
02529 argno,
02530 sRefSet_unparseUnconstrainedPlain (othersets),
02531 thisargno,
02532 sRef_unconstrainedName (thisset),
02533 exprNode_unparse (f), exprNodeList_unparse (args)),
02534 el->loc);
02535 }
02536 else
02537 {
02538 voptgenerror
02539 (FLG_EVALORDER,
02540 message
02541 ("Argument %d modifies %q, set by argument %d (order of"
02542 " evaluation of actual parameters is undefined): %s(%q)",
02543 argno, sRef_unparse (thisset), thisargno,
02544 exprNode_unparse (f), exprNodeList_unparse (args)),
02545 el->loc);
02546 }
02547 }
02548 }
02549 }
02550 }
02551
02552 } end_sRefSet_realElements;
02553 }
02554 }
02555
02556 static void
02557 checkSequencing (exprNode f, exprNodeList args)
02558 {
02559 if (exprNodeList_size (args) > 1)
02560 {
02561 int i;
02562 exprNode el;
02563
02564
02565
02566 for (i = 0; i < args->nelements; i++)
02567 {
02568 el = args->elements[i];
02569
02570 if (!exprNode_isError (el))
02571 {
02572 checkSequencingOne (f, args, el, i + 1);
02573 }
02574 }
02575
02576 }
02577 }
02578
02579
02580
02581
02582
02583 static void
02584 checkGlobMods ( exprNode f,
02585 uentry le, exprNodeList args,
02586 exprNode ret, int specialArgs)
02587 {
02588 bool isSpec = FALSE;
02589 bool hasMods = FALSE;
02590 cstring fname;
02591 globSet usesGlobs = globSet_undefined;
02592 sRefSet mods = sRefSet_undefined;
02593 bool freshMods = FALSE;
02594 uentryList params = uentryList_undefined;
02595
02596
02597
02598
02599
02600 setCodePoint ();
02601
02602 if (!uentry_isValid (le))
02603 {
02604 ctype fr = ctype_realType (f->typ);
02605
02606 if (ctype_isFunction (fr))
02607 {
02608 params = ctype_argsFunction (fr);
02609 }
02610 else
02611 {
02612 params = uentryList_missingParams;
02613 }
02614
02615 if (!context_getFlag (FLG_MODNOMODS)
02616 && !context_getFlag (FLG_GLOBUNSPEC))
02617 {
02618 checkUnspecCall (f, params, args);
02619 }
02620
02621 return;
02622 }
02623
02624 fname = uentry_rawName (le);
02625
02626 setCodePoint ();
02627
02628 if (uentry_isFunction (le))
02629 {
02630 params = uentry_getParams (le);
02631 mods = uentry_getMods (le);
02632 hasMods = uentry_hasMods (le);
02633 usesGlobs = uentry_getGlobs (le);
02634 isSpec = uentry_isSpecified (le);
02635 }
02636 else
02637 {
02638 ctype ct = ctype_realType (uentry_getType (le));
02639
02640 llassertprint (uentry_isVar (le) && ctype_isFunction (ct),
02641 ("checkModGlobs: uentry not a function: %s",
02642 uentry_unparse (le)));
02643
02644 params = ctype_argsFunction (ct);
02645 }
02646
02647
02648
02649
02650
02651 setCodePoint ();
02652
02653
02654 globSet_allElements (usesGlobs, el)
02655 {
02656 if (sRef_isValid (el))
02657 {
02658 if (sRef_isInternalState (el) || sRef_isSystemState (el))
02659 {
02660 context_usedGlobal (el);
02661 exprNode_checkUse (f, el, f->loc);
02662
02663 if (context_checkInternalUse ())
02664 {
02665 if (!context_globAccess (el))
02666 {
02667 if (sRef_isSystemState (el)
02668 && !context_getFlag (FLG_MODFILESYSTEM))
02669 {
02670 ;
02671 }
02672 else
02673 {
02674 voptgenerror
02675 (FLG_INTERNALGLOBS,
02676 message
02677 ("Called procedure %s may access %q, but "
02678 "globals list does not include globals %s",
02679 exprNode_unparse (f),
02680 sRef_unparse (el),
02681 cstring_makeLiteralTemp (sRef_isInternalState (el)
02682 ? "internalState"
02683 : "fileSystem")),
02684 f->loc);
02685 }
02686 }
02687 }
02688 }
02689 else if (sRef_isNothing (el) || sRef_isSpecState (el))
02690 {
02691 ;
02692 }
02693 else
02694 {
02695 uentry gle = sRef_getUentry (el);
02696 sRef sr = sRef_updateSref (el);
02697
02698 if (sRef_isUndefGlob (el))
02699 {
02700 sRef_setDefined (sr, f->loc);
02701 exprNode_checkSet (f, sr);
02702 }
02703 else
02704 {
02705
02706
02707
02708
02709 if (sRef_isAllocated (el))
02710 {
02711 exprNode_checkSet (f, sr);
02712 }
02713 else
02714 {
02715 if (sRef_isStateUndefined (sr))
02716 {
02717 voptgenerror
02718 (FLG_GLOBSTATE,
02719 message
02720 ("%s %q used by function undefined before call: %s",
02721 sRef_getScopeName (sr),
02722 sRef_unparse (sr),
02723 exprNode_unparse (f)),
02724 f->loc);
02725 sRef_setDefined (sr, f->loc);
02726 }
02727 exprNode_checkUse (f, sr, f->loc);
02728 }
02729
02730 checkGlobUse (gle, TRUE, f);
02731 }
02732
02733 if (sRef_isKilledGlob (el))
02734 {
02735 sRef_kill (sr, f->loc);
02736 context_usedGlobal (sr);
02737 }
02738 }
02739 }
02740 } end_globSet_allElements;
02741
02742
02743
02744
02745
02746 if (context_hasMods () || context_getFlag (FLG_MODNOMODS))
02747 {
02748 sRefSet smods = sRefSet_undefined;
02749
02750
02751
02752
02753
02754
02755
02756
02757
02758
02759 setCodePoint ();
02760
02761 sRefSet_allElements (mods, s)
02762 {
02763 if (sRef_isKindSpecial (s))
02764 {
02765 if (sRef_isSpecInternalState (s))
02766 {
02767 if (context_getFlag (FLG_MODINTERNALSTRICT))
02768 {
02769 exprNode_checkCallModifyVal (s, args, f, ret);
02770 }
02771 else
02772 {
02773 sRefSet mmods = context_modList ();
02774
02775 sRefSet_allElements (mmods, el)
02776 {
02777 if (sRef_isInternalState (el))
02778 {
02779 sRef_setModified (el);
02780 }
02781 } end_sRefSet_allElements ;
02782 }
02783 }
02784 else
02785 {
02786 exprNode_checkCallModifyVal (s, args, f, ret);
02787 }
02788 }
02789 else
02790 {
02791 sRef rb = sRef_getRootBase (s);
02792
02793 if (sRef_isGlobal (rb))
02794 {
02795 context_usedGlobal (rb);
02796 }
02797
02798 if (sRef_isFileStatic (s)
02799 && !fileId_equal (fileloc_fileId (f->loc),
02800 fileloc_fileId (uentry_whereDefined (le))))
02801 {
02802 smods = sRefSet_insert (smods, s);
02803 }
02804 else
02805 {
02806 exprNode_checkCallModifyVal (s, args, f, ret);
02807 }
02808 }
02809 } end_sRefSet_allElements;
02810
02811 setCodePoint ();
02812
02813
02814
02815
02816
02817
02818 if (!sRefSet_isDefined (smods))
02819 {
02820 mods = sRefSet_newCopy (mods);
02821 freshMods = TRUE;
02822
02823 sRefSet_allElements (smods, el)
02824 {
02825 bool res = sRefSet_delete (mods, el);
02826
02827 llassert (res);
02828 } end_sRefSet_allElements;
02829
02830 sRefSet_free (smods);
02831
02832 }
02833
02834 }
02835 else if (sRefSet_isDefined (mods))
02836 {
02837 setCodePoint ();
02838
02839 sRefSet_allElements (mods, s)
02840 {
02841 sRef rb = sRef_getRootBase (s);
02842
02843 setCodePoint ();
02844
02845 if (sRef_isParam (rb))
02846 {
02847 sRef b = sRef_fixBaseParam (s, args);
02848
02849 if (sRef_isObserver (b))
02850 {
02851 exprNode e = exprNodeList_nth (args, sRef_getParam (rb));
02852
02853 if (optgenerror
02854 (FLG_MODOBSERVER,
02855 message ("Function call may modify observer%q: %s",
02856 sRef_unparsePreOpt (b), exprNode_unparse (e)),
02857 exprNode_loc (e)))
02858 {
02859 sRef_showExpInfo (b);
02860 }
02861 }
02862 }
02863 } end_sRefSet_allElements;
02864 }
02865 else
02866 {
02867 if (!hasMods)
02868 {
02869 if (context_getFlag (FLG_MODOBSERVERUNCON))
02870 {
02871 exprNodeList_elements (args, e)
02872 {
02873 if (exprNode_isDefined (e))
02874 {
02875 sRef s = exprNode_getSref (e);
02876
02877 if (sRef_isObserver (s)
02878 && ctype_isMutable (sRef_getType (s)))
02879 {
02880 if (optgenerror
02881 (FLG_MODOBSERVERUNCON,
02882 message
02883 ("Call to unconstrained function %s may modify observer%q: %s",
02884 exprNode_unparse (f),
02885 sRef_unparsePreOpt (s), exprNode_unparse (e)),
02886 exprNode_loc (e)))
02887 {
02888 sRef_showExpInfo (s);
02889 }
02890 }
02891 }
02892 } end_exprNodeList_elements;
02893 }
02894 }
02895 }
02896
02897 checkAnyCall (f, fname, params, args, hasMods, mods, isSpec, specialArgs);
02898
02899 ret->uses = sRefSet_union (ret->uses, f->uses);
02900 ret->sets = sRefSet_union (ret->sets, f->sets);
02901 ret->msets = sRefSet_union (ret->msets, f->msets);
02902
02903 if (freshMods)
02904 {
02905
02906
02907
02908
02909
02910 sRefSet_free (mods);
02911 }
02912
02913 setCodePoint ();
02914 }
02915
02916 void checkGlobUse (uentry glob, bool isCall, exprNode e)
02917 {
02918 if (uentry_isVar (glob))
02919 {
02920 if (context_inFunctionLike ())
02921 {
02922 sRef sr = uentry_getSref (glob);
02923
02924 context_usedGlobal (sr);
02925
02926 if (context_checkGlobUse (glob))
02927 {
02928 if (!context_globAccess (sr))
02929 {
02930 if (isCall)
02931 {
02932 voptgenerror
02933 (FLG_GLOBALS,
02934 message ("Called procedure %s may access %s %q",
02935 exprNode_unparse (e),
02936 sRef_unparseScope (sr),
02937 uentry_getName (glob)),
02938 e->loc);
02939 }
02940 else
02941 {
02942 voptgenerror
02943 (FLG_GLOBALS,
02944 message ("Undocumented use of %s %s",
02945 sRef_unparseScope (sr),
02946 exprNode_unparse (e)),
02947 e->loc);
02948 }
02949 }
02950 }
02951 }
02952 }
02953 else
02954 {
02955 llbug (message ("Global not variable: %q", uentry_unparse (glob)));
02956 }
02957 }
02958
02959 static exprNode
02960 functionCallSafe ( exprNode f,
02961 ctype t, exprNodeList args)
02962 {
02963
02964 cstring fname = exprNode_unparse (f);
02965 uentry le = exprNode_getUentry (f);
02966 exprNode ret = exprNode_createPartialCopy (f);
02967 int special;
02968
02969 setCodePoint ();
02970
02971 ret->typ = ctype_returnValue (t);
02972 ret->kind = XPR_CALL;
02973
02974 ret->edata = exprData_makeCall (f, args);
02975
02976
02977
02978
02979
02980
02981
02982 if (context_getFlag (FLG_EVALORDER))
02983 {
02984 exprNodeList_elements (args, current)
02985 {
02986 if (exprNode_isDefined (current))
02987 {
02988 exprNode_addUse (current, current->sref);
02989 }
02990 } end_exprNodeList_elements;
02991
02992 if (context_maybeSet (FLG_EVALORDER) || context_maybeSet (FLG_EVALORDERUNCON))
02993 {
02994 checkSequencing (f, args);
02995 }
02996
02997 exprNodeList_elements (args, current)
02998 {
02999 if (exprNode_isDefined (current) && sRef_isMeaningful (current->sref))
03000 {
03001 exprNode_addUse (ret, sRef_makeDerived (current->sref));
03002 }
03003 } end_exprNodeList_elements ;
03004 }
03005
03006 special = checkArgs (le, f, t, args, ret);
03007 checkGlobMods (f, le, args, ret, special);
03008
03009 setCodePoint ();
03010
03011 if (uentry_isValid (le)
03012 && (uentry_isFunction (le)
03013 || (uentry_isVariable (le)
03014 && ctype_isFunction (uentry_getType (le)))))
03015 {
03016 exitkind exk = uentry_getExitCode (le);
03017
03018
03019
03020 ret->sref = uentry_returnedRef (le, args);
03021
03022 if (uentry_isFunction (le) && exprNodeList_size (args) >= 1)
03023 {
03024 qual nullPred = uentry_nullPred (le);
03025
03026 if (qual_isTrueNull (nullPred))
03027 {
03028 exprNode arg = exprNodeList_head (args);
03029
03030 if (exprNode_isDefined (arg))
03031 {
03032 ret->guards = guardSet_addFalseGuard (ret->guards, arg->sref);
03033 }
03034 }
03035 else if (qual_isFalseNull (nullPred))
03036 {
03037 exprNode arg = exprNodeList_head (args);
03038
03039 if (exprNode_isDefined (arg))
03040 {
03041 ret->guards = guardSet_addTrueGuard (ret->guards, arg->sref);
03042 }
03043 }
03044 else
03045 {
03046 llassert (qual_isUnknown (nullPred));
03047 }
03048 }
03049
03050 if (exitkind_isConditionalExit (exk))
03051 {
03052
03053
03054
03055
03056
03057
03058
03059 exprNode firstArg;
03060
03061 llassert (!exprNodeList_isEmpty (args));
03062 firstArg = exprNodeList_head (args);
03063
03064 if (exprNode_isDefined (firstArg)
03065 && !guardSet_isEmpty (firstArg->guards))
03066 {
03067 usymtab_trueBranch (guardSet_undefined);
03068 usymtab_altBranch (guardSet_undefined);
03069
03070 if (exitkind_isTrueExit (exk))
03071 {
03072 usymtab_popBranches (firstArg,
03073 exprNode_makeMustExit (),
03074 exprNode_undefined,
03075 TRUE, TRUEEXITCLAUSE);
03076 }
03077 else
03078 {
03079 usymtab_popBranches (firstArg,
03080 exprNode_undefined,
03081 exprNode_makeMustExit (),
03082 TRUE, FALSEEXITCLAUSE);
03083 }
03084 }
03085
03086 ret->exitCode = XK_MAYEXIT;
03087 }
03088 else if (exitkind_mustExit (exk))
03089 {
03090 ret->exitCode = XK_MUSTEXIT;
03091 }
03092 else if (exitkind_couldExit (exk))
03093 {
03094 ret->exitCode = XK_MAYEXIT;
03095 }
03096 else
03097 {
03098 ;
03099 }
03100
03101 if (cstring_equalLit (fname, "exit"))
03102 {
03103 if (exprNodeList_size (args) == 1)
03104 {
03105 exprNode arg = exprNodeList_head (args);
03106
03107 if (exprNode_isDefined (arg) && exprNode_knownIntValue (arg))
03108 {
03109 long int val = multiVal_forceInt (exprNode_getValue (arg));
03110
03111 if (val != 0)
03112 {
03113 voptgenerror
03114 (FLG_EXITARG,
03115 message
03116 ("Argument to exit has implementation defined behavior: %s",
03117 exprNode_unparse (arg)),
03118 exprNode_loc (arg));
03119 }
03120 }
03121 }
03122 }
03123 }
03124 else
03125 {
03126 ret->sref = defref;
03127 exprNode_checkSetAny (ret, uentry_rawName (le));
03128 }
03129
03130 return (ret);
03131 }
03132
03133
03134
03135
03136
03137 uentry
03138 exprNode_getUentry (exprNode e)
03139 {
03140 if (exprNode_isError (e))
03141 {
03142 return uentry_undefined;
03143 }
03144 else
03145 {
03146 cstring s = exprNode_rootVarName (e);
03147 uentry ue = usymtab_lookupSafe (s);
03148
03149 return ue;
03150 }
03151 }
03152
03153 exprNode
03154 exprNode_makeInitBlock (lltok brace, exprNodeList inits)
03155 {
03156 exprNode ret = exprNode_createPlain (ctype_unknown);
03157
03158 ret->kind = XPR_INITBLOCK;
03159 ret->edata = exprData_makeCall (exprNode_undefined, inits);
03160 ret->loc = fileloc_update (ret->loc, lltok_getLoc (brace));
03161
03162 return (ret);
03163 }
03164
03165 exprNode
03166 exprNode_functionCall ( exprNode f, exprNodeList args)
03167 {
03168 ctype t;
03169
03170 setCodePoint ();
03171
03172 if (exprNode_isUndefined (f))
03173 {
03174 exprNode_free (f);
03175 exprNodeList_free (args);
03176 return exprNode_undefined;
03177 }
03178
03179 t = exprNode_getType (f);
03180
03181 if (sRef_isLocalVar (f->sref))
03182 {
03183 exprNode_checkUse (f, f->sref, f->loc);
03184
03185 if (sRef_possiblyNull (f->sref))
03186 {
03187 if (!usymtab_isGuarded (f->sref))
03188 {
03189 if (optgenerror (FLG_NULLDEREF,
03190 message ("Function call using %s pointer %q",
03191 sRef_nullMessage (f->sref),
03192 sRef_unparse (f->sref)),
03193 f->loc))
03194 {
03195 sRef_showNullInfo (f->sref);
03196 sRef_setNullError (f->sref);
03197 }
03198 }
03199 }
03200 }
03201
03202 setCodePoint ();
03203
03204 if (ctype_isRealFunction (t))
03205 {
03206 exprNode ret = functionCallSafe (f, t, args);
03207 setCodePoint ();
03208 return ret;
03209 }
03210 else if (ctype_isUnknown (t))
03211 {
03212 exprNode ret = exprNode_createPartialCopy (f);
03213 cstring tstring;
03214
03215 setCodePoint ();
03216
03217 ret->typ = t;
03218 exprNodeList_elements (args, current)
03219 {
03220 if (exprNode_isDefined (current))
03221 {
03222 exprNode_checkUse (ret, current->sref, ret->loc);
03223
03224
03225
03226
03227
03228 exprNode_addUse (ret, sRef_makeDerived (current->sref));
03229 exprNode_mergeUSs (ret, current);
03230 }
03231 } end_exprNodeList_elements;
03232
03233 ret->edata = exprData_makeCall (f, args);
03234 ret->kind = XPR_CALL;
03235
03236 tstring = cstring_copy (exprNode_unparse (f));
03237
03238 cstring_markOwned (tstring);
03239 exprNode_checkSetAny (ret, tstring);
03240
03241 return (ret);
03242 }
03243 else
03244 {
03245 voptgenerror (FLG_TYPE,
03246 message ("Call to non-function (type %t): %s", t,
03247 exprNode_unparse (f)),
03248 f->loc);
03249 exprNode_free (f);
03250 exprNodeList_free (args);
03251
03252 return (exprNode_makeError ());
03253 }
03254 }
03255
03256 exprNode
03257 exprNode_fieldAccess ( exprNode s, cstring f)
03258 {
03259 exprNode ret = exprNode_createPartialCopy (s);
03260
03261 ret->kind = XPR_FACCESS;
03262
03263 if (exprNode_isError (s))
03264 {
03265 ret->edata = exprData_makeField (s, f);
03266 return ret;
03267 }
03268 else
03269 {
03270 ctype t = exprNode_getType (s);
03271 ctype tr = ctype_realType (t);
03272
03273 checkMacroParen (s);
03274
03275 ret->edata = exprData_makeField (s, f);
03276
03277 if (ctype_isStructorUnion (tr))
03278 {
03279 uentry tf = uentryList_lookupField (ctype_getFields (tr), f);
03280
03281 if (uentry_isUndefined (tf))
03282 {
03283 voptgenerror (FLG_TYPE,
03284 message ("Access non-existent field %s of %t: %s", f, t,
03285 exprNode_unparse (ret)),
03286 s->loc);
03287
03288 return (ret);
03289 }
03290 else
03291 {
03292 uentry_setUsed (tf, exprNode_loc (ret));
03293
03294 ret->typ = uentry_getType (tf);
03295 checkSafeUse (ret, s->sref);
03296
03297 ret->sref = sRef_makeField (s->sref, uentry_rawName (tf));
03298 return (ret);
03299 }
03300 }
03301 else
03302 {
03303 if (ctype_isRealAbstract (tr))
03304 {
03305 voptgenerror
03306 (FLG_ABSTRACT,
03307 message ("Access field of abstract type (%t): %s.%s",
03308 t, exprNode_unparse (s), f),
03309 s->loc);
03310 ret->typ = ctype_unknown;
03311 }
03312 else
03313 {
03314 if (ctype_isKnown (tr))
03315 {
03316 voptgenerror
03317 (FLG_TYPE,
03318 message
03319 ("Access field of non-struct or union (%t): %s.%s",
03320 t, exprNode_unparse (s), f),
03321 s->loc);
03322
03323 ret->typ = ctype_unknown;
03324 }
03325 else
03326 {
03327 cstring sn = cstring_copy (f);
03328
03329 checkSafeUse (ret, s->sref);
03330 cstring_markOwned (sn);
03331 ret->sref = sRef_makeField (s->sref, sn);
03332
03333 return (ret);
03334 }
03335 }
03336 return (ret);
03337 }
03338 }
03339 BADEXIT;
03340 }
03341
03342 exprNode
03343 exprNode_addParens ( lltok lpar, exprNode e)
03344 {
03345 exprNode ret = exprNode_createPartialCopy (e);
03346
03347 ret->loc = fileloc_update (ret->loc, lltok_getLoc (lpar));
03348 ret->kind = XPR_PARENS;
03349 ret->edata = exprData_makeUop (e, lpar);
03350
03351 if (!exprNode_isError (e))
03352 {
03353 ret->exitCode = e->exitCode;
03354 ret->canBreak = e->canBreak;
03355 ret->mustBreak = e->mustBreak;
03356 ret->isJumpPoint = e->isJumpPoint;
03357 ret->sref = e->sref;
03358 }
03359
03360 return ret;
03361 }
03362
03363 exprNode
03364 exprNode_arrowAccess ( exprNode s, cstring f)
03365 {
03366 exprNode ret = exprNode_createPartialCopy (s);
03367
03368 ret->edata = exprData_makeField (s, f);
03369 ret->kind = XPR_ARROW;
03370
03371 if (exprNode_isError (s))
03372 {
03373 return (ret);
03374 }
03375 else
03376 {
03377 ctype t = exprNode_getType (s);
03378 ctype tr = ctype_realType (t);
03379
03380 checkMacroParen (s);
03381
03382 (void) ctype_fixArrayPtr (tr);
03383
03384 if (ctype_isRealPointer (tr))
03385 {
03386 ctype b = ctype_realType (ctype_baseArrayPtr (tr));
03387
03388 if (ctype_isStructorUnion (b))
03389 {
03390 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
03391
03392 if (sRef_isKnown (s->sref) && sRef_possiblyNull (s->sref))
03393 {
03394 if (!usymtab_isGuarded (s->sref) && !context_inProtectVars ())
03395 {
03396 if (optgenerror
03397 (FLG_NULLDEREF,
03398 message ("Arrow access from %s pointer%q: %s",
03399 sRef_nullMessage (s->sref),
03400 sRef_unparsePreOpt (s->sref),
03401 exprNode_unparse (ret)),
03402 s->loc))
03403 {
03404 sRef_showNullInfo (s->sref);
03405 sRef_setNullError (s->sref);
03406 }
03407 }
03408 }
03409
03410 if (uentry_isUndefined (fentry))
03411 {
03412 voptgenerror
03413 (FLG_TYPE,
03414 message ("Access non-existent field %s of %t: %s",
03415 f, t, exprNode_unparse (ret)),
03416 s->loc);
03417 ret->typ = ctype_unknown;
03418
03419 return (ret);
03420 }
03421 else
03422 {
03423
03424
03425
03426
03427
03428
03429
03430
03431
03432 uentry_setUsed (fentry, exprNode_loc (ret));
03433 ret->typ = uentry_getType (fentry);
03434
03435 exprNode_checkUse (ret, s->sref, s->loc);
03436
03437
03438 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
03439 return (ret);
03440 }
03441 }
03442 else
03443 {
03444 if (ctype_isRealAbstract (tr))
03445 {
03446 ctype xrt = ctype_forceRealType (tr);
03447
03448 voptgenerror
03449 (FLG_ABSTRACT,
03450 message ("Arrow access field of abstract type (%t): %s->%s",
03451 t, exprNode_unparse (s), f),
03452 s->loc);
03453
03454
03455
03456
03457
03458 if (ctype_isRealPointer (xrt) &&
03459 (b = ctype_realType (ctype_baseArrayPtr (xrt)),
03460 ctype_isStructorUnion (b)))
03461 {
03462 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
03463 ret->typ = uentry_getType (fentry);
03464 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
03465 }
03466 else
03467 {
03468 ret->typ = ctype_unknown;
03469 ret->sref = sRef_undefined;
03470 }
03471 }
03472 else
03473 {
03474 if (ctype_isUnknown (tr)) {
03475 cstring sn = cstring_copy (f);
03476
03477 DPRINTF (("Here: %s", exprNode_unparse (s)));
03478
03479 exprNode_checkUse (ret, s->sref, s->loc);
03480 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
03481
03482 cstring_markOwned (sn);
03483 ret->sref = sRef_makeArrow (s->sref, sn);
03484
03485 ret->kind = XPR_ARROW;
03486 return (ret);
03487 } else {
03488 voptgenerror
03489 (FLG_TYPE,
03490 message ("Arrow access field of non-struct or union "
03491 "pointer (%t): %s->%s",
03492 t, exprNode_unparse (s), f),
03493 s->loc);
03494
03495 ret->typ = ctype_unknown;
03496 ret->sref = sRef_undefined;
03497 }
03498 }
03499 }
03500 }
03501 else
03502 {
03503 if (!ctype_isUnknown (tr))
03504 {
03505 voptgenerror
03506 (FLG_TYPE,
03507 message ("Arrow access of non-pointer (%t): %s->%s",
03508 t, exprNode_unparse (s), f),
03509 s->loc);
03510
03511 ret->typ = ctype_unknown;
03512 ret->sref = sRef_undefined;
03513 }
03514 else
03515 {
03516 cstring sn = cstring_copy (f);
03517
03518 DPRINTF (("Here: %s", exprNode_unparse (s)));
03519
03520 exprNode_checkUse (ret, s->sref, s->loc);
03521 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
03522
03523 cstring_markOwned (sn);
03524 ret->sref = sRef_makeArrow (s->sref, sn);
03525
03526 ret->kind = XPR_ARROW;
03527 return (ret);
03528 }
03529 }
03530
03531 return (ret);
03532 }
03533 BADEXIT;
03534 }
03535
03536
03537
03538
03539
03540 exprNode
03541 exprNode_postOp ( exprNode e, lltok op)
03542 {
03543
03544
03545 ctype t;
03546 exprNode ret = exprNode_createPartialCopy (e);
03547
03548 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
03549 ret->kind = XPR_POSTOP;
03550 ret->edata = exprData_makeUop (e, op);
03551
03552 if (!exprNode_isDefined (e))
03553 {
03554 return ret;
03555 }
03556
03557 checkMacroParen (e);
03558
03559 exprNode_checkUse (ret, e->sref, e->loc);
03560 exprNode_checkSet (ret, e->sref);
03561
03562 t = exprNode_getType (e);
03563
03564 if (sRef_isUnsafe (e->sref))
03565 {
03566 voptgenerror (FLG_MACROPARAMS,
03567 message ("Operand of %s is macro parameter (non-functional): %s%s",
03568 lltok_unparse (op), exprNode_unparse (e), lltok_unparse (op)),
03569 e->loc);
03570 sRef_makeSafe (e->sref);
03571 sRef_makeSafe (ret->sref);
03572 }
03573
03574 if (ctype_isForceRealNumeric (&t) || ctype_isRealAP (t))
03575 {
03576 ret->typ = e->typ;
03577 }
03578 else
03579 {
03580 if (ctype_isRealAbstract (t))
03581 {
03582 voptgenerror
03583 (FLG_ABSTRACT,
03584 message ("Operand of %s is abstract type (%t): %s",
03585 lltok_unparse (op), t, exprNode_unparse (e)),
03586 e->loc);
03587 }
03588 else
03589 {
03590 voptgenerror
03591 (FLG_TYPE,
03592 message ("Operand of %s is non-numeric (%t): %s",
03593 lltok_unparse (op), t, exprNode_unparse (e)),
03594 e->loc);
03595 }
03596 ret->typ = ctype_unknown;
03597 }
03598
03599
03600
03601 exprNode_checkModify (e, ret);
03602
03603 return ret;
03604 }
03605
03606 exprNode
03607 exprNode_preOp ( exprNode e, lltok op)
03608 {
03609 bool checkMod = FALSE;
03610 ctype te, tr;
03611 int opid = lltok_getTok (op);
03612 exprNode ret = exprNode_createSemiCopy (e);
03613
03614 exprNode_copySets (ret, e);
03615
03616 multiVal_free (ret->val);
03617 ret->val = multiVal_undefined;
03618 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
03619 ret->kind = XPR_PREOP;
03620 ret->edata = exprData_makeUop (e, op);
03621
03622 if (exprNode_isError (e))
03623 {
03624 return ret;
03625 }
03626
03627 checkMacroParen (e);
03628
03629 te = exprNode_getType (e);
03630 tr = ctype_realType (te);
03631
03632 if (opid != TAMPERSAND)
03633 {
03634 exprNode_checkUse (ret, e->sref, e->loc);
03635
03636 if (ctype_isRealAbstract (tr)
03637 && (!(ctype_isRealBool (te) && (opid == TEXCL))))
03638 {
03639 if (optgenerror (FLG_ABSTRACT,
03640 message ("Operand of %s is abstract type (%t): %s",
03641 lltok_unparse (op), tr,
03642 exprNode_unparse (ret)),
03643 e->loc))
03644 {
03645 tr = te = ctype_unknown;
03646 ret->typ = ctype_unknown;
03647 sRef_setNullError (e->sref);
03648 }
03649 }
03650 }
03651
03652 switch (opid)
03653 {
03654 case INC_OP:
03655 case DEC_OP:
03656 if (sRef_isMacroParamRef (e->sref))
03657 {
03658 voptgenerror
03659 (FLG_MACROPARAMS,
03660 message ("Operand of %s is macro parameter (non-functional): %s",
03661 lltok_unparse (op), exprNode_unparse (ret)),
03662 e->loc);
03663 }
03664 else
03665 {
03666 exprNode_checkSet (ret, e->sref);
03667 }
03668
03669 if (ctype_isForceRealNumeric (&tr) || ctype_isRealAP (tr))
03670 {
03671 }
03672 else
03673 {
03674 if (context_msgStrictOps ())
03675 {
03676 voptgenerror
03677 (FLG_STRICTOPS,
03678 message ("Operand of %s is non-numeric (%t): %s",
03679 lltok_unparse (op), te, exprNode_unparse (ret)),
03680 e->loc);
03681 }
03682 ret->typ = ctype_int;
03683 }
03684
03685 checkMod = TRUE;
03686 break;
03687
03688 case TMINUS:
03689 case TPLUS:
03690 if (ctype_isForceRealNumeric (&tr))
03691 {
03692 if (opid == TMINUS)
03693 {
03694 ret->val = multiVal_invert (exprNode_getValue (e));
03695 }
03696 else
03697 {
03698 ret->val = multiVal_copy (exprNode_getValue (e));
03699 }
03700 }
03701 else
03702 {
03703 if (context_msgStrictOps ())
03704 {
03705 voptgenerror
03706 (FLG_STRICTOPS,
03707 message ("Operand of %s is non-numeric (%t): %s",
03708 lltok_unparse (op), te, exprNode_unparse (ret)),
03709 e->loc);
03710 }
03711
03712 ret->typ = ctype_int;
03713 }
03714 break;
03715
03716 case TEXCL:
03717 guardSet_flip (ret->guards);
03718
03719 if (ctype_isRealBool (te))
03720 {
03721 ;
03722 }
03723 else
03724 {
03725 if (ctype_isRealPointer (tr))
03726 {
03727 if (sRef_isKnown (e->sref))
03728 {
03729 ret->guards = guardSet_addFalseGuard (ret->guards, e->sref);
03730 }
03731
03732 voptgenerror2n
03733 (FLG_BOOLOPS, FLG_PTRNEGATE,
03734 message ("Operand of %s is non-boolean (%t): %s",
03735 lltok_unparse (op), te, exprNode_unparse (ret)),
03736 e->loc);
03737 }
03738 else
03739 {
03740 voptgenerror
03741 (FLG_BOOLOPS,
03742 message ("Operand of %s is non-boolean (%t): %s",
03743 lltok_unparse (op), te, exprNode_unparse (ret)),
03744 e->loc);
03745 }
03746
03747 ret->typ = ctype_bool;
03748 }
03749 break;
03750
03751 case TTILDE:
03752 if (ctype_isForceRealInt (&tr))
03753 {
03754 }
03755 else
03756 {
03757 if (context_msgStrictOps ())
03758 {
03759 voptgenerror
03760 (FLG_STRICTOPS,
03761 message ("Operand of %s is non-integer (%t): %s",
03762 lltok_unparse (op), te, exprNode_unparse (ret)),
03763 e->loc);
03764 }
03765
03766 if (ctype_isInt (e->typ))
03767 {
03768 ret->typ = e->typ;
03769 }
03770 else
03771 {
03772 ret->typ = ctype_int;
03773 }
03774 }
03775 break;
03776
03777 case TAMPERSAND:
03778 ret->typ = ctype_makePointer (e->typ);
03779
03780 if (sRef_isKnown (e->sref))
03781 {
03782 ret->sref = sRef_makeAddress (e->sref);
03783 }
03784
03785 break;
03786
03787 case TMULT:
03788
03789 if (ctype_isAP (tr))
03790 {
03791 ret->typ = ctype_baseArrayPtr (e->typ);
03792 }
03793 else
03794 {
03795 if (ctype_isKnown (te))
03796 {
03797 if (ctype_isFunction (te))
03798 {
03799 ret->typ = e->typ;
03800
03801 voptgenerror
03802 (FLG_FCNDEREF,
03803 message ("Dereference of function type (%t): %s",
03804 te, exprNode_unparse (ret)),
03805 e->loc);
03806 }
03807 else
03808 {
03809 voptgenerror (FLG_TYPE,
03810 message ("Dereference of non-pointer (%t): %s",
03811 te, exprNode_unparse (ret)),
03812 e->loc);
03813 ret->typ = ctype_unknown;
03814 }
03815 }
03816 else
03817 {
03818 ret->typ = ctype_unknown;
03819 }
03820
03821 }
03822
03823 if (sRef_isKnown (e->sref))
03824 {
03825 if (sRef_possiblyNull (e->sref))
03826 {
03827 if (!usymtab_isGuarded (e->sref) && !context_inProtectVars ())
03828 {
03829 if (optgenerror
03830 (FLG_NULLDEREF,
03831 message ("Dereference of %s pointer %q: %s",
03832 sRef_nullMessage (e->sref),
03833 sRef_unparse (e->sref),
03834 exprNode_unparse (ret)),
03835 e->loc))
03836 {
03837 sRef_showNullInfo (e->sref);
03838 sRef_setNotNull (e->sref, e->loc);
03839 }
03840 }
03841 }
03842
03843 ret->sref = sRef_makePointer (e->sref);
03844 }
03845 break;
03846
03847 default:
03848 llbug (message ("exprNode_preOp: unhandled op: %s", lltok_unparse (op)));
03849 }
03850
03851 if (checkMod)
03852 {
03853 exprNode_checkModify (e, ret);
03854 }
03855
03856 return ret;
03857 }
03858
03859
03860
03861
03862
03863
03864
03865
03866
03867 static
03868 ctype sizeof_resultType (void)
03869 {
03870 static ctype sizet = ctype_unknown;
03871
03872 if (ctype_isUnknown (sizet))
03873 {
03874 if (usymtab_existsType (cstring_makeLiteralTemp ("size_t")))
03875 {
03876 sizet = uentry_getAbstractType (usymtab_lookup (cstring_makeLiteralTemp ("size_t")));
03877 }
03878 else
03879 {
03880 sizet = ctype_ulint;
03881 }
03882 }
03883 return sizet;
03884 }
03885
03886 exprNode
03887 exprNode_sizeofType ( qtype qt)
03888 {
03889 exprNode ret = exprNode_create (sizeof_resultType ());
03890 ctype ct = qtype_getType (qt);
03891
03892 ret->kind = XPR_SIZEOFT;
03893 ret->edata = exprData_makeSizeofType (qt);
03894
03895 voptgenerror (FLG_SIZEOFTYPE,
03896 message ("Parameter to sizeof is type %s: %s",
03897 ctype_unparse (ct),
03898 exprNode_unparse (ret)),
03899 ret->loc);
03900
03901 return (ret);
03902 }
03903
03904 exprNode
03905 exprNode_alignofType ( qtype qt)
03906 {
03907 exprNode ret = exprNode_create (sizeof_resultType ());
03908 ctype ct = qtype_getType (qt);
03909
03910 ret->kind = XPR_ALIGNOFT;
03911 ret->edata = exprData_makeSizeofType (qt);
03912
03913 voptgenerror (FLG_SIZEOFTYPE,
03914 message ("Parameter to alignof is type %s: %s",
03915 ctype_unparse (ct),
03916 exprNode_unparse (ret)),
03917 ret->loc);
03918
03919 return (ret);
03920 }
03921
03922 exprNode exprNode_offsetof (qtype qt, cstringList s)
03923 {
03924 exprNode ret = exprNode_create (sizeof_resultType ());
03925 ctype ct = qtype_getType (qt);
03926
03927 ret->kind = XPR_OFFSETOF;
03928 ret->edata = exprData_makeOffsetof (qt, s);
03929
03930 if (!ctype_isRealSU (ct))
03931 {
03932 voptgenerror (FLG_TYPE,
03933 message ("First parameter to offsetof is not a "
03934 "struct or union type (type %s): %s",
03935 ctype_unparse (ct),
03936 exprNode_unparse (ret)),
03937 ret->loc);
03938 }
03939 else
03940 {
03941 ctype lt = ct;
03942
03943 cstringList_elements (s, el) {
03944 uentryList fields;
03945 uentry fld;
03946
03947 if (ctype_isUndefined (lt))
03948 {
03949 break;
03950 }
03951 else if (!ctype_isRealSU (lt))
03952 {
03953 voptgenerror (FLG_TYPE,
03954 message ("Inner offsetof type is not a "
03955 "struct or union type (type %s before field %s): %s",
03956 ctype_unparse (lt), el,
03957 exprNode_unparse (ret)),
03958 ret->loc);
03959 break;
03960 }
03961 else
03962 {
03963 fields = ctype_getFields (ctype_realType (lt));
03964 fld = uentryList_lookupField (fields, el);
03965 DPRINTF (("Try: %s / %s", ctype_unparse (lt), el));
03966
03967 if (uentry_isUndefined (fld))
03968 {
03969 if (ctype_equal (lt, ct)) {
03970 voptgenerror (FLG_TYPE,
03971 message ("Field %s in offsetof is not the "
03972 "name of a field of %s: %s",
03973 el,
03974 ctype_unparse (ct),
03975 exprNode_unparse (ret)),
03976 ret->loc);
03977 } else {
03978 voptgenerror (FLG_TYPE,
03979 message ("Deep field %s in offsetof is not the "
03980 "name of a field of %s: %s",
03981 el,
03982 ctype_unparse (lt),
03983 exprNode_unparse (ret)),
03984 ret->loc);
03985 }
03986 }
03987 else
03988 {
03989 lt = uentry_getType (fld);
03990 }
03991 }
03992 } end_cstringList_elements;
03993
03994
03995 }
03996
03997 return (ret);
03998 }
03999
04000 exprNode
04001 exprNode_sizeofExpr ( exprNode e)
04002 {
04003 exprNode ret;
04004
04005 if (exprNode_isUndefined (e))
04006 {
04007 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
04008 ret->edata = exprData_makeSingle (e);
04009 ret->typ = sizeof_resultType ();
04010 ret->kind = XPR_SIZEOF;
04011 }
04012 else
04013 {
04014 uentry u = exprNode_getUentry (e);
04015
04016 ret = exprNode_createPartialCopy (e);
04017 ret->edata = exprData_makeSingle (e);
04018
04019 ret->typ = sizeof_resultType ();
04020 ret->kind = XPR_SIZEOF;
04021
04022 if (uentry_isValid (u)
04023 && uentry_isRefParam (u)
04024 && ctype_isRealArray (uentry_getType (u)))
04025 {
04026 voptgenerror
04027 (FLG_SIZEOFFORMALARRAY,
04028 message ("Parameter to sizeof is an array-type function parameter: %s",
04029 exprNode_unparse (ret)),
04030 ret->loc);
04031 }
04032 }
04033
04034
04035
04036
04037
04038 return (ret);
04039 }
04040
04041 exprNode
04042 exprNode_alignofExpr ( exprNode e)
04043 {
04044 exprNode ret;
04045
04046 if (exprNode_isUndefined (e))
04047 {
04048 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
04049 }
04050 else
04051 {
04052 ret = exprNode_createPartialCopy (e);
04053 }
04054
04055 ret->edata = exprData_makeSingle (e);
04056 ret->typ = sizeof_resultType ();
04057 ret->kind = XPR_ALIGNOF;
04058
04059
04060
04061
04062
04063 return (ret);
04064 }
04065
04066 exprNode
04067 exprNode_cast ( lltok tok, exprNode e, qtype q)
04068 {
04069 ctype c;
04070 ctype t;
04071 exprNode ret;
04072
04073 if (exprNode_isError (e))
04074 {
04075 qtype_free (q);
04076 lltok_release (tok);
04077 return exprNode_undefined;
04078 }
04079
04080 checkMacroParen (e);
04081
04082 c = qtype_getType (q);
04083 t = exprNode_getType (e);
04084
04085 ret = exprNode_createPartialCopy (e);
04086
04087 ret->loc = fileloc_update (ret->loc, lltok_getLoc (tok));
04088 ret->typ = c;
04089 ret->kind = XPR_CAST;
04090 ret->edata = exprData_makeCast (tok, e, q);
04091
04092 if (ctype_isRealSU (ctype_getBaseType (sRef_getType (e->sref))))
04093 {
04094
04095
04096
04097
04098
04099
04100
04101
04102 ret->sref = sRef_copy (e->sref);
04103 usymtab_addForceMustAlias (ret->sref, e->sref);
04104 sRef_setTypeFull (ret->sref, c);
04105 DPRINTF (("Cast: %s -> %s", sRef_unparseFull (e->sref),
04106 sRef_unparseFull (ret->sref)));
04107 }
04108 else
04109 {
04110 ret->sref = e->sref;
04111 sRef_setTypeFull (ret->sref, c);
04112 DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref)));
04113 }
04114
04115
04116
04117
04118
04119
04120
04121
04122
04123 if (ctype_isVoid (c))
04124 {
04125 ;
04126 }
04127 else if (ctype_isRealAP (c))
04128 {
04129 ctype bc = ctype_getBaseType (c);
04130 ctype bt = ctype_getBaseType (t);
04131 ctype rt = ctype_realType (t);
04132
04133 if (ctype_isFunction (ctype_baseArrayPtr (ctype_realType (c)))
04134 && (ctype_isArrayPtr (rt)
04135 && !ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
04136 {
04137 voptgenerror
04138 (FLG_CASTFCNPTR,
04139 message ("Cast from function pointer type (%t) to "
04140 "non-function pointer (%t): %s",
04141 c, t, exprNode_unparse (ret)),
04142 e->loc);
04143 }
04144
04145 if (!ctype_isFunction (ctype_baseArrayPtr (c))
04146 && (ctype_isArrayPtr (rt)
04147 && ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
04148 {
04149 voptgenerror
04150 (FLG_CASTFCNPTR,
04151 message ("Cast from non-function pointer type (%t) to "
04152 "function pointer (%t): %s",
04153 c, t, exprNode_unparse (ret)),
04154 e->loc);
04155 }
04156
04157 if (exprNode_isZero (e) && context_getFlag (FLG_ZEROPTR) &&
04158 !(ctype_isRealAbstract (bc)
04159 && context_hasAccess (ctype_typeId (bc))))
04160 {
04161 ;
04162 }
04163 else
04164 {
04165 if (ctype_isRealAbstract (bc)
04166 && !context_hasAccess (ctype_typeId (bc)))
04167 {
04168 if (ctype_isVoidPointer (t) || ctype_isUnknown (t))
04169 {
04170 vnoptgenerror
04171 (FLG_ABSTVOIDP,
04172 message ("Cast to underlying abstract type %t: %s",
04173 c, exprNode_unparse (ret)),
04174 e->loc);
04175 }
04176 else
04177 {
04178 voptgenerror
04179 (FLG_ABSTRACT,
04180 message ("Cast to underlying abstract type %t: %s",
04181 c, exprNode_unparse (ret)),
04182 e->loc);
04183 }
04184 }
04185
04186 if (ctype_isRealAbstract (bt)
04187 && !context_hasAccess (ctype_typeId (bt)))
04188 {
04189 if (ctype_isUnknown (c) || ctype_isVoidPointer (c))
04190 {
04191 vnoptgenerror
04192 (FLG_ABSTVOIDP,
04193 message ("Cast from underlying abstract type %t: %s",
04194 t, exprNode_unparse (ret)),
04195 e->loc);
04196 }
04197 else
04198 {
04199 voptgenerror
04200 (FLG_ABSTRACT,
04201 message ("Cast from underlying abstract type %t: %s",
04202 t, exprNode_unparse (ret)),
04203 e->loc);
04204 }
04205 }
04206 }
04207 }
04208 else
04209 {
04210 ctype bt = ctype_realType (ctype_getBaseType (t));
04211 ctype bc = ctype_realType (ctype_getBaseType (c));
04212
04213 if (ctype_isAbstract (bt) && !context_hasAccess (ctype_typeId (bt)))
04214 {
04215 if (ctype_match (c, t))
04216 {
04217 if (ctype_equal (c, t))
04218 {
04219 voptgenerror
04220 (FLG_TYPE,
04221 message ("Redundant cast involving abstract type %t: %s",
04222 bt, exprNode_unparse (ret)),
04223 e->loc);
04224 }
04225 }
04226 else
04227 {
04228 voptgenerror
04229 (FLG_ABSTRACT,
04230 message ("Cast from abstract type %t: %s",
04231 bt, exprNode_unparse (ret)),
04232 e->loc);
04233 }
04234 }
04235
04236 if (ctype_isAbstract (bc)
04237 && !context_hasAccess (ctype_typeId (bc)))
04238 {
04239 if (ctype_match (c, t))
04240 {
04241 ;
04242 }
04243 else
04244 {
04245 voptgenerror
04246 (FLG_ABSTRACT,
04247 message ("Cast to abstract type %t: %s", bc,
04248 exprNode_unparse (ret)),
04249 e->loc);
04250 }
04251 }
04252 }
04253
04254 if (ctype_isAbstract (c))
04255 {
04256 if (sRef_isExposed (e->sref) || sRef_isOnly (e->sref))
04257 {
04258
04259 sRef_clearExKindComplete (ret->sref, fileloc_undefined);
04260 }
04261 else
04262 {
04263 if (ctype_isVisiblySharable (t)
04264 && sRef_isExternallyVisible (e->sref)
04265 && !(ctype_isAbstract (t)
04266 && context_hasAccess (ctype_typeId (t))))
04267 {
04268 voptgenerror
04269 (FLG_CASTEXPOSE,
04270 message ("Cast to abstract type from externally visible "
04271 "mutable storage exposes rep of %s: %s",
04272 ctype_unparse (c),
04273 exprNode_unparse (e)),
04274 e->loc);
04275 }
04276 }
04277 }
04278
04279 return (ret);
04280 }
04281
04282 static bool
04283 evaluationOrderUndefined (lltok op)
04284 {
04285 int opid = lltok_getTok (op);
04286
04287 return (opid != AND_OP && opid != OR_OP);
04288 }
04289
04290 static bool checkIntegral ( exprNode e1,
04291 exprNode e2,
04292 exprNode ret,
04293 lltok op)
04294 {
04295 bool error = FALSE;
04296
04297 ctype te1 = exprNode_getType (e1);
04298 ctype te2 = exprNode_getType (e2);
04299
04300 ctype tr1 = ctype_realishType (te1);
04301 ctype tr2 = ctype_realishType (te2);
04302
04303 if (ctype_isForceRealInt (&tr1) && ctype_isForceRealInt (&tr2))
04304 {
04305 ;
04306 }
04307 else
04308 {
04309 if (context_msgStrictOps ())
04310 {
04311 if (!ctype_isInt (tr1) && !ctype_isInt (tr2))
04312 {
04313 if (ctype_sameName (te1, te2))
04314 {
04315 error = optgenerror
04316 (FLG_STRICTOPS,
04317 message ("Operands of %s are non-integer (%t): %s",
04318 lltok_unparse (op), te1,
04319 exprNode_unparse (ret)),
04320 e1->loc);
04321 }
04322 else
04323 {
04324 error = optgenerror
04325 (FLG_STRICTOPS,
04326 message ("Operands of %s are non-integers (%t, %t): %s",
04327 lltok_unparse (op), te1, te2,
04328 exprNode_unparse (ret)),
04329 e1->loc);
04330 }
04331 }
04332 else if (!ctype_isInt (tr1))
04333 {
04334 error = optgenerror
04335 (FLG_STRICTOPS,
04336 message ("Left operand of %s is non-integer (%t): %s",
04337 lltok_unparse (op), te1, exprNode_unparse (ret)),
04338 e1->loc);
04339 }
04340 else
04341
04342 {
04343 error = optgenerror
04344 (FLG_STRICTOPS,
04345 message ("Right operand of %s is non-integer (%t): %s",
04346 lltok_unparse (op), te2, exprNode_unparse (ret)),
04347 e2->loc);
04348 }
04349 }
04350 }
04351
04352 return !error;
04353 }
04354
04355
04356
04357
04358
04359
04360
04361
04362
04363
04364 static exprNode
04365 exprNode_makeOp ( exprNode e1, exprNode e2,
04366 lltok op)
04367 {
04368 ctype te1, te2, tr1, tr2, tret;
04369 int opid = lltok_getTok (op);
04370 bool hasError = FALSE;
04371 exprNode ret;
04372
04373 if (exprNode_isError (e1))
04374 {
04375 ret = exprNode_createPartialNVCopy (e2);
04376 }
04377 else
04378 {
04379 ret = exprNode_createPartialNVCopy (e1);
04380 }
04381
04382 ret->val = multiVal_undefined;
04383 ret->kind = XPR_OP;
04384 ret->edata = exprData_makeOp (e1, e2, op);
04385
04386 if (exprNode_isError (e1) || exprNode_isError (e2))
04387 {
04388 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
04389 || opid == EQ_OP || opid == NE_OP
04390 || opid == AND_OP || opid == OR_OP)
04391 {
04392 ret->typ = ctype_bool;
04393 }
04394
04395 if (exprNode_isDefined (e1))
04396 {
04397 exprNode_checkUse (ret, e1->sref, e1->loc);
04398 }
04399
04400 if (exprNode_isDefined (e2))
04401 {
04402 exprNode_mergeUSs (ret, e2);
04403 exprNode_checkUse (ret, e2->sref, e2->loc);
04404 }
04405
04406 return ret;
04407 }
04408
04409 tret = ctype_unknown;
04410 te1 = exprNode_getType (e1);
04411 DPRINTF (("te1 = %s / %s", exprNode_unparse (e1), ctype_unparse (te1)));
04412
04413 te2 = exprNode_getType (e2);
04414
04415 tr1 = ctype_realishType (te1);
04416 tr2 = ctype_realishType (te2);
04417
04418 if (opid == OR_OP)
04419 {
04420 ret->guards = guardSet_or (ret->guards, e2->guards);
04421 }
04422 else if (opid == AND_OP)
04423 {
04424 ret->guards = guardSet_and (ret->guards, e2->guards);
04425 }
04426 else
04427 {
04428
04429 }
04430
04431 if (opid == EQ_OP || opid == NE_OP)
04432 {
04433 exprNode temp1 = e1, temp2 = e2;
04434
04435
04436
04437 if (exprNode_isNullValue (e1) || exprNode_isUnknownConstant (e1))
04438 {
04439 temp1 = e2; temp2 = e1;
04440 }
04441
04442 if (exprNode_isNullValue (temp2) || exprNode_isUnknownConstant (temp2))
04443 {
04444 reflectNullTest (temp1, (opid == NE_OP));
04445 guardSet_free (ret->guards);
04446 ret->guards = guardSet_copy (temp1->guards);
04447 }
04448 }
04449
04450 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
04451 || opid == EQ_OP || opid == NE_OP || opid == AND_OP || opid == OR_OP)
04452 {
04453 tret = ctype_bool;
04454 }
04455
04456 if (anyAbstract (tr1, tr2) &&
04457 (!((ctype_isRealBool (te1) || ctype_isRealBool (te2)) &&
04458 (opid == AND_OP || opid == OR_OP
04459 || opid == EQ_OP || opid == NE_OP))))
04460 {
04461 abstractOpError (tr1, tr2, op, e1, e2, e1->loc, e2->loc);
04462 }
04463 else if (ctype_isUnknown (te1) || ctype_isUnknown (te2))
04464 {
04465
04466 }
04467 else
04468 {
04469 switch (opid)
04470 {
04471 case TMULT:
04472 case TDIV:
04473 case MUL_ASSIGN:
04474 case DIV_ASSIGN:
04475
04476 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
04477 break;
04478
04479 case TPLUS:
04480 case TMINUS:
04481 case SUB_ASSIGN:
04482 case ADD_ASSIGN:
04483
04484 tr1 = ctype_fixArrayPtr (tr1);
04485
04486 if ((ctype_isRealPointer (tr1) && !exprNode_isNullValue (e1))
04487 && (!ctype_isRealPointer (tr2) && ctype_isRealInt (tr2)))
04488 {
04489
04490
04491 if (context_msgPointerArith ())
04492 {
04493 voptgenerror
04494 (FLG_POINTERARITH,
04495 message ("Pointer arithmetic (%t, %t): %s",
04496 te1, te2, exprNode_unparse (ret)),
04497 e1->loc);
04498 }
04499
04500 if (sRef_possiblyNull (e1->sref)
04501 && !usymtab_isGuarded (e1->sref))
04502 {
04503 voptgenerror
04504 (FLG_NULLPOINTERARITH,
04505 message ("Pointer arithmetic involving possibly "
04506 "null pointer %s: %s",
04507 exprNode_unparse (e1),
04508 exprNode_unparse (ret)),
04509 e1->loc);
04510 }
04511
04512 ret->sref = sRef_copy (e1->sref);
04513
04514 sRef_setNullError (ret->sref);
04515
04516
04517
04518
04519
04520
04521
04522 if (sRef_isOnly (ret->sref)
04523 || sRef_isFresh (ret->sref))
04524 {
04525 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
04526 }
04527
04528 tret = e1->typ;
04529 }
04530 else if ((!ctype_isRealPointer(tr1) && ctype_isRealInt (tr1))
04531 && (ctype_isRealPointer (tr2) && !exprNode_isNullValue (e2)))
04532 {
04533 if (context_msgPointerArith ())
04534 {
04535 voptgenerror
04536 (FLG_POINTERARITH,
04537 message ("Pointer arithmetic (%t, %t): %s",
04538 te1, te2, exprNode_unparse (ret)),
04539 e1->loc);
04540 }
04541
04542 if (sRef_possiblyNull (e1->sref)
04543 && !usymtab_isGuarded (e1->sref))
04544 {
04545 voptgenerror
04546 (FLG_NULLPOINTERARITH,
04547 message ("Pointer arithmetic involving possibly "
04548 "null pointer %s: %s",
04549 exprNode_unparse (e2),
04550 exprNode_unparse (ret)),
04551 e2->loc);
04552 }
04553
04554 ret->sref = sRef_copy (e2->sref);
04555
04556 sRef_setNullError (ret->sref);
04557
04558
04559
04560
04561
04562
04563
04564 if (sRef_isOnly (ret->sref)
04565 || sRef_isFresh (ret->sref)) {
04566 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
04567 }
04568
04569 tret = e2->typ;
04570 ret->sref = e2->sref;
04571 }
04572 else
04573 {
04574 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
04575 }
04576
04577 break;
04578
04579 case LEFT_ASSIGN:
04580 case RIGHT_ASSIGN:
04581 case LEFT_OP:
04582 case RIGHT_OP:
04583 case TAMPERSAND:
04584 case AND_ASSIGN:
04585 case TCIRC:
04586 case TBAR:
04587 case XOR_ASSIGN:
04588 case OR_ASSIGN:
04589 {
04590 bool reported = FALSE;
04591 flagcode code = FLG_BITWISEOPS;
04592
04593 if (opid == LEFT_OP || opid == LEFT_ASSIGN
04594 || opid == RIGHT_OP || opid == RIGHT_ASSIGN) {
04595 code = FLG_SHIFTSIGNED;
04596 }
04597
04598 if (!ctype_isUnsigned (tr1))
04599 {
04600 if (exprNode_isNonNegative (e1)) {
04601 ;
04602 } else {
04603 reported = optgenerror
04604 (code,
04605 message ("Left operand of %s is not unsigned value (%t): %s",
04606 lltok_unparse (op), te1,
04607 exprNode_unparse (ret)),
04608 e1->loc);
04609
04610 if (reported) {
04611 te1 = ctype_uint;
04612 }
04613 }
04614 }
04615 else
04616 {
04617
04618 if (code != FLG_SHIFTSIGNED
04619 && !ctype_isUnsigned (tr2))
04620 {
04621 if (!exprNode_isNonNegative (e2)) {
04622 reported = optgenerror
04623 (code,
04624 message ("Right operand of %s is not unsigned value (%t): %s",
04625 lltok_unparse (op), te2,
04626 exprNode_unparse (ret)),
04627 e2->loc);
04628 }
04629 }
04630 }
04631
04632 if (!reported)
04633 {
04634 if (!checkIntegral (e1, e2, ret, op)) {
04635 te1 = ctype_unknown;
04636 }
04637 }
04638
04639 DPRINTF (("Set: %s", ctype_unparse (te1)));
04640
04641
04642
04643
04644
04645 tret = ctype_widest (te1, te2);
04646 break;
04647 }
04648 case MOD_ASSIGN:
04649 case TPERCENT:
04650 if (checkIntegral (e1, e2, ret, op)) {
04651 tret = te1;
04652 } else {
04653 tret = ctype_unknown;
04654 }
04655 break;
04656 case EQ_OP:
04657 case NE_OP:
04658 case TLT:
04659 case TGT:
04660 if ((ctype_isReal (tr1) && !ctype_isInt (tr1))
04661 || (ctype_isReal (tr2) && !ctype_isInt (tr2)))
04662 {
04663 ctype rtype = tr1;
04664 bool fepsilon = FALSE;
04665
04666 if (!ctype_isReal (rtype) || ctype_isInt (rtype))
04667 {
04668 rtype = tr2;
04669 }
04670
04671 if (opid == TLT || opid == TGT)
04672 {
04673 uentry ue1 = exprNode_getUentry (e1);
04674 uentry ue2 = exprNode_getUentry (e2);
04675
04676
04677
04678
04679
04680
04681 if (uentry_isVariable (ue1))
04682 {
04683 cstring uname = uentry_rawName (ue1);
04684
04685 if (cstring_equalLit (uname, "FLT_EPSILON")
04686 || cstring_equalLit (uname, "DBL_EPSILON")
04687 || cstring_equalLit (uname, "LDBL_EPSILON"))
04688 {
04689 fepsilon = TRUE;
04690 }
04691 }
04692
04693 if (uentry_isVariable (ue2))
04694 {
04695 cstring uname = uentry_rawName (ue2);
04696
04697 if (cstring_equalLit (uname, "FLT_EPSILON")
04698 || cstring_equalLit (uname, "DBL_EPSILON")
04699 || cstring_equalLit (uname, "LDBL_EPSILON"))
04700 {
04701 fepsilon = TRUE;
04702 }
04703 }
04704 }
04705
04706 if (fepsilon)
04707 {
04708 ;
04709 }
04710 else
04711 {
04712 voptgenerror
04713 (FLG_REALCOMPARE,
04714 message ("Dangerous comparison involving %s types: %s",
04715 ctype_unparse (rtype),
04716 exprNode_unparse (ret)),
04717 ret->loc);
04718 }
04719 }
04720
04721 case LE_OP:
04722 case GE_OP:
04723
04724
04725
04726
04727
04728 if (!exprNode_matchTypes (e1, e2))
04729 {
04730 hasError = gentypeerror
04731 (te1, e1, te2, e2,
04732 message ("Operands of %s have incompatible types (%t, %t): %s",
04733 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
04734 e1->loc);
04735
04736 }
04737
04738 if (hasError
04739 || (ctype_isForceRealNumeric (&tr1)
04740 && ctype_isForceRealNumeric (&tr2)) ||
04741 (ctype_isRealPointer (tr1) && ctype_isRealPointer (tr2)))
04742 {
04743 ;
04744 }
04745 else
04746 {
04747 if ((ctype_isRealNumeric (tr1) && ctype_isRealPointer (tr2)) ||
04748 (ctype_isRealPointer (tr1) && ctype_isRealNumeric (tr2)))
04749 {
04750 voptgenerror
04751 (FLG_PTRNUMCOMPARE,
04752 message ("Comparison of pointer and numeric (%t, %t): %s",
04753 te1, te2, exprNode_unparse (ret)),
04754 e1->loc);
04755 }
04756 else
04757 {
04758 (void) checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
04759 }
04760 tret = ctype_bool;
04761 }
04762
04763
04764
04765 if ((opid == EQ_OP || opid == NE_OP) &&
04766 ctype_isDirectBool (tr1) && ctype_isDirectBool (tr2))
04767 {
04768
04769
04770
04771
04772 if (uentry_isVariable (exprNode_getUentry (e1))
04773 || uentry_isVariable (exprNode_getUentry (e2)))
04774 {
04775
04776
04777
04778
04779 if (exprNode_isFalseConstant (e1)
04780 || exprNode_isFalseConstant (e2))
04781 {
04782 ;
04783 }
04784 else
04785 {
04786 voptgenerror
04787 (FLG_BOOLCOMPARE,
04788 message
04789 ("Use of %q with %s variables (risks inconsistency because "
04790 "of multiple true values): %s",
04791 cstring_makeLiteral ((opid == EQ_OP) ? "==" : "!="),
04792 context_printBoolName (), exprNode_unparse (ret)),
04793 e1->loc);
04794 }
04795 }
04796 }
04797 break;
04798
04799 case AND_OP:
04800 case OR_OP:
04801
04802 if (ctype_isForceRealBool (&tr1) && ctype_isForceRealBool (&tr2))
04803 {
04804 ;
04805 }
04806 else
04807 {
04808 if (context_maybeSet (FLG_BOOLOPS))
04809 {
04810 if (!ctype_isRealBool (te1) && !ctype_isRealBool (te2))
04811 {
04812 if (ctype_sameName (te1, te2))
04813 {
04814 voptgenerror
04815 (FLG_BOOLOPS,
04816 message ("Operands of %s are non-boolean (%t): %s",
04817 lltok_unparse (op), te1,
04818 exprNode_unparse (ret)),
04819 e1->loc);
04820 }
04821 else
04822 {
04823 voptgenerror
04824 (FLG_BOOLOPS,
04825 message
04826 ("Operands of %s are non-booleans (%t, %t): %s",
04827 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
04828 e1->loc);
04829 }
04830 }
04831 else if (!ctype_isRealBool (te1))
04832 {
04833 voptgenerror
04834 (FLG_BOOLOPS,
04835 message ("Left operand of %s is non-boolean (%t): %s",
04836 lltok_unparse (op), te1, exprNode_unparse (ret)),
04837 e1->loc);
04838 }
04839 else if (!ctype_isRealBool (te2))
04840 {
04841 voptgenerror
04842 (FLG_BOOLOPS,
04843 message ("Right operand of %s is non-boolean (%t): %s",
04844 lltok_unparse (op), te2, exprNode_unparse (ret)),
04845 e2->loc);
04846 }
04847 else
04848 {
04849 ;
04850 }
04851 }
04852 tret = ctype_bool;
04853 }
04854 break;
04855 default: {
04856 TPRINTF (("opid = %d", opid));
04857 llfatalbug
04858 (cstring_makeLiteral
04859 ("There has been a problem in the parser. This is due to a bug "
04860 "in either lclint, bison or gcc version 2.95 optimizations, "
04861 "but it has not been confirmed. Please try rebuidling LCLint "
04862 "without the -O<n> option."));
04863 }
04864 }
04865 }
04866
04867 DPRINTF (("Return type: %s", ctype_unparse (tret)));
04868 ret->typ = tret;
04869
04870 exprNode_checkUse (ret, e1->sref, e1->loc);
04871 exprNode_mergeUSs (ret, e2);
04872 exprNode_checkUse (ret, e2->sref, e2->loc);
04873
04874 return ret;
04875 }
04876
04877 exprNode
04878 exprNode_op ( exprNode e1, exprNode e2,
04879 lltok op)
04880 {
04881 exprNode ret;
04882
04883 checkMacroParen (e1);
04884 checkMacroParen (e2);
04885
04886 if (evaluationOrderUndefined (op) && context_maybeSet (FLG_EVALORDER))
04887 {
04888 checkExpressionDefined (e1, e2, op);
04889 }
04890
04891 ret = exprNode_makeOp (e1, e2, op);
04892 return (ret);
04893 }
04894
04895 static
04896 void exprNode_checkAssignMod (exprNode e1, exprNode ret)
04897 {
04898
04899
04900
04901
04902
04903
04904
04905 sRef ref = exprNode_getSref (e1);
04906
04907 DPRINTF (("Check assign mod: %s",
04908 sRef_unparseFull (ref)));
04909
04910 if (sRef_isObserver (ref)
04911 || ((sRef_isFileStatic (ref) || sRef_isGlobal (ref))
04912 && ctype_isArray (ctype_realType (sRef_getType (ref)))))
04913 {
04914 sRef base = sRef_getBase (ref);
04915
04916 if (sRef_isValid (base) && sRef_isObserver (base))
04917 {
04918 exprNode_checkModify (e1, ret);
04919 }
04920 else
04921 {
04922 exprNode_checkModifyVal (e1, ret);
04923 }
04924 }
04925 else
04926 {
04927 exprNode_checkModify (e1, ret);
04928 }
04929 }
04930
04931 exprNode
04932 exprNode_assign ( exprNode e1,
04933 exprNode e2, lltok op)
04934 {
04935 bool isalloc = FALSE;
04936 bool isjustalloc = FALSE;
04937 exprNode ret;
04938
04939 DPRINTF (("%s [%s] <- %s [%s]",
04940 exprNode_unparse (e1),
04941 ctype_unparse (e1->typ),
04942 exprNode_unparse (e2),
04943 ctype_unparse (e2->typ)));
04944
04945 if (lltok_getTok (op) != TASSIGN)
04946 {
04947 ret = exprNode_makeOp (e1, e2, op);
04948 }
04949 else
04950 {
04951 ret = exprNode_createPartialCopy (e1);
04952 ret->kind = XPR_ASSIGN;
04953 ret->edata = exprData_makeOp (e1, e2, op);
04954
04955 if (!exprNode_isError (e2))
04956 {
04957 ret->sets = sRefSet_union (ret->sets, e2->sets);
04958 ret->msets = sRefSet_union (ret->msets, e2->msets);
04959 ret->uses = sRefSet_union (ret->uses, e2->uses);
04960 }
04961 }
04962
04963 checkExpressionDefined (e1, e2, op);
04964
04965 if (exprNode_isError (e1))
04966 {
04967 if (!exprNode_isError (e2))
04968 {
04969 ret->loc = fileloc_update (ret->loc, e2->loc);
04970 }
04971 else
04972 {
04973 ret->loc = fileloc_update (ret->loc, g_currentloc);
04974 }
04975 }
04976
04977 if (!exprNode_isError (e2))
04978 {
04979 checkMacroParen (e2);
04980 }
04981
04982 if (exprNode_isDefined (e1))
04983 {
04984 if (sRef_isMacroParamRef (e1->sref))
04985 {
04986 if (context_inIterDef ())
04987 {
04988 uentry ue = sRef_getUentry (e1->sref);
04989
04990 if (uentry_isYield (ue))
04991 {
04992 ;
04993 }
04994 else
04995 {
04996 if (fileloc_isDefined (e1->loc))
04997 {
04998 voptgenerror
04999 (FLG_MACROPARAMS,
05000 message ("Assignment to non-yield iter parameter: %q",
05001 sRef_unparse (e1->sref)),
05002 e1->loc);
05003 }
05004 else
05005 {
05006 voptgenerror
05007 (FLG_MACROPARAMS,
05008 message ("Assignment to non-yield iter parameter: %q",
05009 sRef_unparse (e1->sref)),
05010 g_currentloc);
05011 }
05012 }
05013 }
05014 else
05015 {
05016 if (fileloc_isDefined (e1->loc))
05017 {
05018 voptgenerror
05019 (FLG_MACROASSIGN,
05020 message ("Assignment to macro parameter: %q",
05021 sRef_unparse (e1->sref)),
05022 e1->loc);
05023 }
05024 else
05025 {
05026 voptgenerror
05027 (FLG_MACROASSIGN,
05028 message ("Assignment to macro parameter: %q",
05029 sRef_unparse (e1->sref)),
05030 g_currentloc);
05031 }
05032 }
05033 }
05034 else
05035 {
05036 exprNode_checkAssignMod (e1, ret);
05037 }
05038
05039 if (exprNode_isDefined (e2))
05040 {
05041 if (lltok_getTok (op) == TASSIGN)
05042 {
05043 ctype te1 = exprNode_getType (e1);
05044 ctype te2 = exprNode_getType (e2);
05045
05046 if (!ctype_forceMatch (te1, te2))
05047 {
05048 if (exprNode_matchLiteral (te1, e2))
05049 {
05050 ;
05051 }
05052 else
05053 {
05054 (void) gentypeerror
05055 (te2, e2, te1, e1,
05056 message ("Assignment of %t to %t: %s %s %s",
05057 te2, te1, exprNode_unparse (e1),
05058 lltok_unparse (op),
05059 exprNode_unparse (e2)),
05060 e1->loc);
05061 }
05062 }
05063 }
05064
05065 exprNode_mergeUSs (ret, e2);
05066 exprNode_checkUse (ret, e2->sref, e2->loc);
05067
05068 doAssign (e1, e2, FALSE);
05069 ret->sref = e1->sref;
05070 }
05071 else
05072 {
05073 if (exprNode_isDefined (e2))
05074 {
05075 exprNode_mergeUSs (ret, e2);
05076 exprNode_checkUse (ret, e2->sref, e2->loc);
05077 }
05078 }
05079
05080 if (sRef_isPointer (e1->sref) && !sRef_isMacroParamRef (e1->sref))
05081 {
05082 exprNode_checkUse (ret, sRef_getBase (e1->sref), e1->loc);
05083 }
05084
05085 isjustalloc = sRef_isJustAllocated (e1->sref);
05086 isalloc = sRef_isAllocated (e1->sref);
05087
05088 if (sRef_isField (e1->sref))
05089 {
05090 sRef root = sRef_getRootBase (sRef_getBase (e1->sref));
05091
05092 if (!sRef_isAllocated (root) && !sRef_isMacroParamRef (root))
05093 {
05094 exprNode_checkUse (ret, root, e1->loc);
05095 }
05096
05097 }
05098
05099
05100
05101
05102
05103 if (!sRef_isMacroParamRef (e1->sref))
05104 {
05105 exprNode_checkSet (ret, e1->sref);
05106 }
05107
05108 if (isjustalloc)
05109 {
05110 sRef_setAllocatedComplete (e1->sref, exprNode_isDefined (e2)
05111 ? e2->loc : e1->loc);
05112 }
05113 else
05114 {
05115 if (isalloc)
05116 {
05117 sRef_setAllocatedShallowComplete (e1->sref, exprNode_loc (e2));
05118 }
05119 }
05120 }
05121
05122 return ret;
05123 }
05124
05125 exprNode
05126 exprNode_cond ( exprNode pred, exprNode ifclause,
05127 exprNode elseclause)
05128 {
05129 exprNode ret;
05130
05131 if (!exprNode_isError (pred))
05132 {
05133 ret = exprNode_createPartialCopy (pred);
05134 checkMacroParen (pred);
05135 exprNode_checkPred (cstring_makeLiteralTemp ("conditional"), pred);
05136
05137 if (!exprNode_isError (ifclause))
05138 {
05139 checkMacroParen (ifclause);
05140
05141 if (!exprNode_isError (elseclause))
05142 {
05143 checkMacroParen (elseclause);
05144
05145 if (!exprNode_matchTypes (ifclause, elseclause))
05146 {
05147 if (gentypeerror
05148 (exprNode_getType (ifclause),
05149 ifclause,
05150 exprNode_getType (elseclause),
05151 elseclause,
05152 message ("Conditional clauses are not of same type: "
05153 "%s (%t), %s (%t)",
05154 exprNode_unparse (ifclause),
05155 exprNode_getType (ifclause),
05156 exprNode_unparse (elseclause),
05157 exprNode_getType (elseclause)),
05158 ifclause->loc))
05159 {
05160 ret->sref = sRef_undefined;
05161 ret->typ = ctype_unknown;
05162 }
05163 }
05164 else
05165 {
05166
05167 ret->sref = ifclause->sref;
05168 ret->typ = ifclause->typ;
05169
05170 if (exprNode_isNullValue (ifclause))
05171 {
05172 ret->typ = elseclause->typ;
05173 }
05174 }
05175
05176 exprNode_checkUse (ret, pred->sref, pred->loc);
05177 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
05178 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
05179
05180 exprNode_mergeCondUSs (ret, ifclause, elseclause);
05181
05182 }
05183 else
05184 {
05185 ret->typ = ifclause->typ;
05186
05187 exprNode_checkUse (pred, pred->sref, pred->loc);
05188 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
05189
05190 exprNode_mergeCondUSs (ret, ifclause, exprNode_undefined);
05191 }
05192 }
05193 else
05194 {
05195 if (!exprNode_isError (elseclause))
05196 {
05197 ret->typ = elseclause->typ;
05198
05199 exprNode_checkUse (pred, pred->sref, pred->loc);
05200 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
05201
05202 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
05203 }
05204 }
05205 }
05206 else
05207 {
05208 if (!exprNode_isError (ifclause))
05209 {
05210 ret = exprNode_createSemiCopy (ifclause);
05211
05212 checkMacroParen (ifclause);
05213
05214 if (!exprNode_isError (elseclause))
05215 {
05216 checkMacroParen (elseclause);
05217
05218 ret->typ = ifclause->typ;
05219
05220 if (!ctype_forceMatch (ifclause->typ, elseclause->typ))
05221 {
05222 if (gentypeerror
05223 (exprNode_getType (ifclause),
05224 ifclause,
05225 exprNode_getType (elseclause),
05226 elseclause,
05227 message ("Conditional clauses are not of same type: "
05228 "%s (%t), %s (%t)",
05229 exprNode_unparse (ifclause),
05230 exprNode_getType (ifclause),
05231 exprNode_unparse (elseclause),
05232 exprNode_getType (elseclause)),
05233 ifclause->loc))
05234 {
05235 ret->typ = ctype_unknown;
05236 }
05237 }
05238
05239 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
05240 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
05241
05242 exprNode_mergeCondUSs (ret, ifclause, elseclause);
05243 }
05244 }
05245 else if (!exprNode_isError (elseclause))
05246 {
05247 ret = exprNode_createSemiCopy (ifclause);
05248
05249 ret->typ = elseclause->typ;
05250 checkMacroParen (elseclause);
05251
05252 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
05253 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
05254 }
05255 else
05256 {
05257 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
05258 }
05259 }
05260
05261 ret->kind = XPR_COND;
05262 ret->edata = exprData_makeCond (pred, ifclause, elseclause);
05263
05264 if (exprNode_isDefined (ifclause) && exprNode_isDefined (elseclause))
05265 {
05266 exprNode_combineControl (ret, ifclause, elseclause);
05267 }
05268
05269 return (ret);
05270 }
05271
05272 exprNode
05273 exprNode_vaArg ( lltok tok, exprNode arg, qtype qt)
05274 {
05275 ctype totype = qtype_getType (qt);
05276 exprNode ret =
05277 exprNode_createPartialLocCopy (arg, fileloc_copy (lltok_getLoc (tok)));
05278 ctype targ;
05279
05280
05281
05282
05283
05284 if (exprNode_isError (arg))
05285 {
05286 }
05287 else
05288 {
05289 targ = exprNode_getType (arg);
05290
05291
05292
05293
05294
05295 if (!ctype_isUA (targ) ||
05296 (!usymId_equal (ctype_typeId (targ),
05297 usymtab_getTypeId (cstring_makeLiteralTemp ("va_list")))))
05298 {
05299 voptgenerror
05300 (FLG_TYPE,
05301 message ("First argument to va_arg is not a va_list (type %t): %s",
05302 targ, exprNode_unparse (arg)),
05303 arg->loc);
05304 }
05305
05306 exprNode_checkSet (ret, arg->sref);
05307 }
05308
05309
05310
05311
05312
05313 ret->typ = totype;
05314 ret->kind = XPR_VAARG;
05315 ret->edata = exprData_makeCast (tok, arg, qt);
05316
05317 return (ret);
05318 }
05319
05320 exprNode exprNode_labelMarker ( cstring label)
05321 {
05322 exprNode ret = exprNode_createPlain (ctype_undefined);
05323 ret->kind = XPR_LABEL;
05324 ret->edata = exprData_makeLiteral (label);
05325 ret->isJumpPoint = TRUE;
05326
05327 return (ret);
05328 }
05329
05330 exprNode exprNode_notReached ( exprNode stmt)
05331 {
05332 if (exprNode_isDefined (stmt))
05333 {
05334 stmt->isJumpPoint = TRUE;
05335
05336
05337 stmt->exitCode = XK_MUSTEXIT;
05338 }
05339
05340 return (stmt);
05341 }
05342
05343 bool exprNode_isDefaultMarker (exprNode e)
05344 {
05345 if (exprNode_isDefined (e))
05346 {
05347 return (e->kind == XPR_DEFAULT || e->kind == XPR_FTDEFAULT);
05348 }
05349
05350 return FALSE;
05351 }
05352
05353 bool exprNode_isCaseMarker (exprNode e)
05354 {
05355 if (exprNode_isDefined (e))
05356 {
05357 return (e->kind == XPR_FTCASE || e->kind == XPR_CASE);
05358 }
05359
05360 return FALSE;
05361 }
05362
05363 bool exprNode_isLabelMarker (exprNode e)
05364 {
05365 if (exprNode_isDefined (e))
05366 {
05367 return (e->kind == XPR_LABEL);
05368 }
05369
05370 return FALSE;
05371 }
05372
05373 exprNode exprNode_caseMarker ( exprNode test, bool fallThrough)
05374 {
05375 exprNode ret = exprNode_createPartialCopy (test);
05376
05377 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
05378
05379 if (exprNode_isError (test)) {
05380 return ret;
05381 }
05382
05383 exprNode_checkUse (ret, test->sref, test->loc);
05384
05385 usymtab_setExitCode (ret->exitCode);
05386
05387 if (ret->mustBreak)
05388 {
05389 usymtab_setMustBreak ();
05390 }
05391
05392 ret->edata = exprData_makeSingle (test);
05393 ret->isJumpPoint = TRUE;
05394
05395 return ret;
05396 }
05397
05398 # if 0
05399 exprNode exprNode_caseStatement ( exprNode test, exprNode stmt, bool fallThrough)
05400 {
05401 exprNode ret = exprNode_createPartialCopy (test);
05402
05403 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
05404 ret->edata = exprData_makePair (test, stmt);
05405 ret->isJumpPoint = TRUE;
05406
05407 if (exprNode_isError (test))
05408 {
05409 return ret;
05410 }
05411
05412 exprNode_checkUse (ret, test->sref, test->loc);
05413
05414 if (exprNode_isError (stmt))
05415 {
05416 return ret;
05417 }
05418
05419 exprNode_mergeUSs (ret, stmt);
05420
05421 ret->exitCode = stmt->exitCode;
05422 ret->mustBreak = stmt->mustBreak;
05423 ret->canBreak = stmt->canBreak;
05424
05425 usymtab_setExitCode (ret->exitCode);
05426
05427 if (ret->mustBreak)
05428 {
05429 usymtab_setMustBreak ();
05430 }
05431
05432 return ret;
05433 }
05434 # endif
05435
05436 exprNode
05437 exprNode_defaultMarker ( lltok def, bool fallThrough)
05438 {
05439 exprNode ret = exprNode_createTok (def);
05440
05441 ret->isJumpPoint = TRUE;
05442 ret->kind = fallThrough ? XPR_FTDEFAULT : XPR_DEFAULT;
05443 return (ret);
05444 }
05445
05446 bool
05447 exprNode_mayEscape (exprNode e)
05448 {
05449 if (exprNode_isDefined (e))
05450 {
05451 return exitkind_couldEscape (e->exitCode);
05452 }
05453 return FALSE;
05454 }
05455
05456 static bool
05457 exprNode_mustBreak (exprNode e)
05458 {
05459 if (exprNode_isDefined (e))
05460 {
05461 return e->mustBreak;
05462 }
05463 return FALSE;
05464 }
05465
05466 bool
05467 exprNode_mustEscape (exprNode e)
05468 {
05469 if (exprNode_isDefined (e))
05470 {
05471 return exitkind_mustEscape (e->exitCode) || exprNode_mustBreak (e);
05472 }
05473
05474 return FALSE;
05475 }
05476
05477 bool
05478 exprNode_errorEscape (exprNode e)
05479 {
05480 if (exprNode_isDefined (e))
05481 {
05482 return exitkind_isError (e->exitCode);
05483 }
05484
05485 return FALSE;
05486 }
05487
05488 exprNode exprNode_concat ( exprNode e1, exprNode e2)
05489 {
05490 exprNode ret = exprNode_createPartialCopy (e1);
05491
05492 ret->edata = exprData_makePair (e1, e2);
05493 ret->kind = XPR_STMTLIST;
05494
05495 if (exprNode_isDefined (e1))
05496 {
05497 ret->isJumpPoint = e1->isJumpPoint;
05498 ret->canBreak = e1->canBreak;
05499 }
05500 else
05501 {
05502 if (exprNode_isDefined (e2))
05503 {
05504 ret->loc = fileloc_update (ret->loc, e2->loc);
05505 }
05506 }
05507
05508 if (exprNode_isDefined (e2))
05509 {
05510 ret->exitCode = e2->exitCode;
05511 ret->mustBreak = e2->mustBreak;
05512 if (e2->canBreak) ret->canBreak = TRUE;
05513 }
05514
05515
05516
05517
05518
05519 if (exprNode_isDefined (e1) && exprNode_isDefined (e2))
05520 {
05521 if ((exprNode_mustEscape (e1) || exprNode_mustBreak (e1))
05522 && !(e2->isJumpPoint))
05523 {
05524 if (context_getFlag (FLG_UNREACHABLE))
05525 {
05526 exprNode nr = e2;
05527
05528 if (e2->kind == XPR_STMT)
05529 {
05530 nr = exprData_getSingle (e2->edata);
05531 }
05532
05533 if ((nr->kind == XPR_TOK
05534 && lltok_isSemi (exprData_getTok (nr->edata))))
05535 {
05536
05537 ret->exitCode = XK_MUSTEXIT;
05538 ret->canBreak = TRUE;
05539 }
05540 else
05541 {
05542 if (optgenerror (FLG_UNREACHABLE,
05543 message ("Unreachable code: %s",
05544 exprNode_unparseFirst (nr)),
05545 exprNode_loc (nr)))
05546 {
05547 ret->isJumpPoint = TRUE;
05548 ret->mustBreak = FALSE;
05549 ret->exitCode = XK_ERROR;
05550 DPRINTF (("Jump point: %s", exprNode_unparse (ret)));
05551 }
05552 else
05553 {
05554 ret->exitCode = XK_MUSTEXIT;
05555 ret->canBreak = TRUE;
05556 }
05557
05558 }
05559 }
05560 }
05561 else
05562 {
05563 if ((e2->kind == XPR_CASE || e2->kind == XPR_DEFAULT))
05564 {
05565
05566
05567
05568
05569
05570
05571
05572 exprNode lastStmt = exprNode_lastStatement (e1);
05573
05574 if (exprNode_isDefined (lastStmt)
05575 && !exprNode_mustEscape (lastStmt)
05576 && !exprNode_mustBreak (lastStmt)
05577 && !exprNode_isCaseMarker (lastStmt)
05578 && !exprNode_isDefaultMarker (lastStmt)
05579 && !exprNode_isLabelMarker (lastStmt))
05580 {
05581 voptgenerror (FLG_CASEBREAK,
05582 cstring_makeLiteral
05583 ("Fall through case (no preceeding break)"),
05584 e2->loc);
05585 }
05586 }
05587 }
05588 }
05589
05590 exprNode_mergeUSs (ret, e2);
05591
05592 usymtab_setExitCode (ret->exitCode);
05593
05594 if (ret->mustBreak)
05595 {
05596 usymtab_setMustBreak ();
05597 }
05598
05599 return ret;
05600 }
05601
05602 exprNode exprNode_createTok ( lltok t)
05603 {
05604 exprNode ret = exprNode_create (ctype_unknown);
05605 ret->kind = XPR_TOK;
05606 ret->edata = exprData_makeTok (t);
05607 return ret;
05608 }
05609
05610 exprNode exprNode_statement ( exprNode e)
05611 {
05612 if (!exprNode_isError (e))
05613 {
05614 exprNode_checkStatement(e);
05615 }
05616
05617 return (exprNode_statementError (e));
05618 }
05619
05620 static exprNode exprNode_statementError ( exprNode e)
05621 {
05622 exprNode ret = exprNode_createPartialCopy (e);
05623
05624 if (!exprNode_isError (e))
05625 {
05626 if (e->kind != XPR_ASSIGN)
05627 {
05628 exprNode_checkUse (ret, e->sref, e->loc);
05629 }
05630
05631 ret->exitCode = e->exitCode;
05632 ret->canBreak = e->canBreak;
05633 ret->mustBreak = e->mustBreak;
05634 }
05635
05636 ret->edata = exprData_makeSingle (e);
05637 ret->kind = XPR_STMT;
05638
05639 return ret;
05640 }
05641
05642 exprNode exprNode_checkExpr ( exprNode e)
05643 {
05644 if (!exprNode_isError (e))
05645 {
05646 if (e->kind != XPR_ASSIGN)
05647 {
05648 exprNode_checkUse (e, e->sref, e->loc);
05649 }
05650 }
05651
05652 return e;
05653 }
05654
05655 void exprNode_produceGuards (exprNode pred)
05656 {
05657 if (!exprNode_isError (pred))
05658 {
05659 if (ctype_isRealPointer (pred->typ))
05660 {
05661 pred->guards = guardSet_addTrueGuard (pred->guards, pred->sref);
05662 }
05663
05664 exprNode_checkUse (pred, pred->sref, pred->loc);
05665 exprNode_resetSref (pred);
05666 }
05667 }
05668
05669 exprNode exprNode_makeBlock ( exprNode e)
05670 {
05671 exprNode ret = exprNode_createPartialCopy (e);
05672
05673 if (!exprNode_isError (e))
05674 {
05675 ret->exitCode = e->exitCode;
05676 ret->canBreak = e->canBreak;
05677 ret->mustBreak = e->mustBreak;
05678 }
05679
05680 ret->edata = exprData_makeSingle (e);
05681 ret->kind = XPR_BLOCK;
05682 return ret;
05683 }
05684
05685 bool exprNode_isBlock (exprNode e)
05686 {
05687 return (exprNode_isDefined (e)
05688 && ((e)->kind == XPR_BLOCK));
05689 }
05690
05691 bool exprNode_isAssign (exprNode e)
05692 {
05693 if (exprNode_isDefined (e))
05694 {
05695 return (e->kind == XPR_ASSIGN);
05696 }
05697
05698 return FALSE;
05699 }
05700
05701 bool exprNode_isEmptyStatement (exprNode e)
05702 {
05703 return (exprNode_isDefined (e)
05704 && (e->kind == XPR_TOK)
05705 && (lltok_isSemi (exprData_getTok (e->edata))));
05706 }
05707
05708 exprNode exprNode_if ( exprNode pred, exprNode tclause)
05709 {
05710 exprNode ret;
05711 bool emptyErr = FALSE;
05712
05713 if (context_maybeSet (FLG_IFEMPTY))
05714 {
05715 if (exprNode_isEmptyStatement (tclause))
05716 {
05717 emptyErr = optgenerror (FLG_IFEMPTY,
05718 cstring_makeLiteral
05719 ("Body of if statement is empty"),
05720 exprNode_loc (tclause));
05721 }
05722 }
05723
05724 if (!emptyErr && context_maybeSet (FLG_IFBLOCK))
05725 {
05726 if (exprNode_isDefined (tclause)
05727 && !exprNode_isBlock (tclause))
05728 {
05729 voptgenerror (FLG_IFBLOCK,
05730 message
05731 ("Body of if statement is not a block: %s",
05732 exprNode_unparse (tclause)),
05733 exprNode_loc (tclause));
05734 }
05735 }
05736
05737 if (exprNode_isError (pred))
05738 {
05739 if (exprNode_isError (tclause))
05740 {
05741 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
05742 }
05743 else
05744 {
05745 ret = exprNode_createPartialCopy (tclause);
05746 }
05747 }
05748 else
05749 {
05750 if (exprNode_mustEscape (pred))
05751 {
05752 voptgenerror
05753 (FLG_UNREACHABLE,
05754 message ("Predicate always exits: %s", exprNode_unparse (pred)),
05755 exprNode_loc (pred));
05756 }
05757
05758 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
05759 exprNode_checkUse (pred, pred->sref, pred->loc);
05760
05761 if (!exprNode_isError (tclause))
05762 {
05763 exprNode_mergeCondUSs (pred, tclause, exprNode_undefined);
05764 }
05765
05766 ret = exprNode_createPartialCopy (pred);
05767 }
05768
05769 ret->kind = XPR_IF;
05770 ret->edata = exprData_makePair (pred, tclause);
05771
05772 ret->exitCode = XK_UNKNOWN;
05773
05774 if (exprNode_isDefined (tclause))
05775 {
05776 ret->exitCode = exitkind_makeConditional (tclause->exitCode);
05777 ret->canBreak = tclause->canBreak;
05778 ret->sets = sRefSet_union (ret->sets, tclause->sets);
05779 ret->msets = sRefSet_union (ret->msets, tclause->msets);
05780 ret->uses = sRefSet_union (ret->uses, tclause->uses);
05781 }
05782
05783 ret->mustBreak = FALSE;
05784
05785 return ret;
05786 }
05787
05788 exprNode exprNode_ifelse ( exprNode pred,
05789 exprNode tclause,
05790 exprNode eclause)
05791 {
05792 exprNode ret;
05793 bool tEmptyErr = FALSE;
05794 bool eEmptyErr = FALSE;
05795
05796 if (context_maybeSet (FLG_IFEMPTY))
05797 {
05798 if (exprNode_isEmptyStatement (tclause))
05799 {
05800 tEmptyErr = optgenerror
05801 (FLG_IFEMPTY,
05802 cstring_makeLiteral
05803 ("Body of if clause of if statement is empty"),
05804 exprNode_loc (tclause));
05805 }
05806
05807 if (exprNode_isEmptyStatement (eclause))
05808 {
05809 eEmptyErr = optgenerror
05810 (FLG_IFEMPTY,
05811 cstring_makeLiteral
05812 ("Body of else clause of if statement is empty"),
05813 exprNode_loc (eclause));
05814 }
05815 }
05816
05817 if (context_maybeSet (FLG_IFBLOCK))
05818 {
05819 if (!tEmptyErr
05820 && exprNode_isDefined (tclause)
05821 && !exprNode_isBlock (tclause))
05822 {
05823 voptgenerror (FLG_IFBLOCK,
05824 message
05825 ("Body of if clause of if statement is not a block: %s",
05826 exprNode_unparse (tclause)),
05827 exprNode_loc (tclause));
05828 }
05829
05830 if (!eEmptyErr
05831 && exprNode_isDefined (eclause)
05832 && !exprNode_isBlock (eclause)
05833 && !(eclause->kind == XPR_IF)
05834 && !(eclause->kind == XPR_IFELSE))
05835 {
05836 voptgenerror
05837 (FLG_IFBLOCK,
05838 message
05839 ("Body of else clause of if statement is not a block: %s",
05840 exprNode_unparse (eclause)),
05841 exprNode_loc (eclause));
05842 }
05843 }
05844
05845 if (context_maybeSet (FLG_ELSEIFCOMPLETE))
05846 {
05847 if (exprNode_isDefined (eclause)
05848 && (eclause->kind == XPR_IF))
05849 {
05850 voptgenerror (FLG_ELSEIFCOMPLETE,
05851 message ("Incomplete else if logic (no final else): %s",
05852 exprNode_unparse (eclause)),
05853 exprNode_loc (eclause));
05854 }
05855 }
05856
05857 if (exprNode_isError (pred))
05858 {
05859 if (exprNode_isError (tclause))
05860 {
05861 if (exprNode_isError (eclause))
05862 {
05863 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
05864 }
05865 else
05866 {
05867 ret = exprNode_createPartialCopy (eclause);
05868 }
05869 }
05870 else
05871 {
05872 ret = exprNode_createPartialCopy (tclause);
05873 }
05874 }
05875 else
05876 {
05877 ret = exprNode_createPartialCopy (pred);
05878
05879 if (exprNode_mustEscape (pred))
05880 {
05881 voptgenerror
05882 (FLG_UNREACHABLE,
05883 message ("Predicate always exits: %s", exprNode_unparse (pred)),
05884 exprNode_loc (pred));
05885 }
05886
05887 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
05888 exprNode_checkUse (ret, pred->sref, pred->loc);
05889
05890 exprNode_mergeCondUSs (ret, tclause, eclause);
05891 }
05892
05893 ret->kind = XPR_IFELSE;
05894 ret->edata = exprData_makeCond (pred, tclause, eclause);
05895
05896 if (exprNode_isDefined (tclause) && exprNode_isDefined (eclause))
05897 {
05898 exprNode_combineControl (ret, tclause, eclause);
05899 ret->loc = fileloc_update (ret->loc, eclause->loc);
05900 }
05901
05902 return ret;
05903 }
05904
05905
05906
05907
05908
05909 static bool
05910 checkSwitchExpr (exprNode test, exprNode e, bool *allpaths)
05911 {
05912 exprNodeSList el = exprNode_flatten (e);
05913 bool mustReturn = TRUE;
05914 bool thisReturn = FALSE;
05915 bool hasDefault = FALSE;
05916 bool hasAllMembers = FALSE;
05917 bool inSwitch = FALSE;
05918 bool isEnumSwitch = FALSE;
05919 bool canBreak = FALSE;
05920 bool fallThrough = FALSE;
05921 ctype ct = ctype_unknown;
05922 enumNameSList usedEnums;
05923 enumNameList enums;
05924
05925 if (exprNode_isDefined (test))
05926 {
05927 ctype ttype;
05928
05929 ct = test->typ;
05930 ttype = ctype_realType (ct);
05931
05932 if (ctype_isEnum (ttype))
05933 {
05934 isEnumSwitch = TRUE;
05935 enums = ctype_elist (ttype);
05936 usedEnums = enumNameSList_new ();
05937 }
05938 }
05939
05940 exprNodeSList_elements (el, current)
05941 {
05942 if (exprNode_isDefined (current))
05943 {
05944 switch (current->kind)
05945 {
05946 case XPR_FTDEFAULT:
05947 case XPR_DEFAULT:
05948 if (hasDefault)
05949 {
05950 voptgenerror
05951 (FLG_CONTROL,
05952 message ("Duplicate default cases in switch"),
05953 exprNode_loc (current));
05954 }
05955
05956 case XPR_FTCASE:
05957 case XPR_CASE:
05958 if (current->kind == XPR_DEFAULT || current->kind == XPR_FTDEFAULT)
05959 {
05960 hasDefault = TRUE;
05961 }
05962 else
05963 {
05964 if (isEnumSwitch)
05965 {
05966 exprNode st = exprData_getSingle (current->edata);
05967 uentry ue = exprNode_getUentry (st);
05968
05969 if (uentry_isValid (ue))
05970 {
05971 cstring cname = uentry_rawName (ue);
05972
05973 if (enumNameList_member (enums, cname))
05974 {
05975 if (enumNameSList_member
05976 (usedEnums, cname))
05977 {
05978 voptgenerror
05979 (FLG_CONTROL,
05980 message ("Duplicate case in switch: %s",
05981 cname),
05982 current->loc);
05983 }
05984 else
05985 {
05986 enumNameSList_addh (usedEnums, cname);
05987 }
05988 }
05989 else
05990 {
05991 voptgenerror
05992 (FLG_TYPE,
05993 message ("Case in switch not %s member: %s",
05994 ctype_unparse (ct), cname),
05995 current->loc);
05996 }
05997 }
05998 }
05999 }
06000
06001 if (inSwitch && !fallThrough)
06002 {
06003 if (!thisReturn || canBreak)
06004 {
06005 mustReturn = FALSE;
06006 }
06007 }
06008
06009 fallThrough = TRUE;
06010 inSwitch = TRUE;
06011 thisReturn = FALSE;
06012 canBreak = FALSE;
06013 break;
06014 default:
06015 thisReturn = thisReturn || exprNode_mustEscape (current);
06016 canBreak = canBreak || current->canBreak;
06017 if (canBreak) fallThrough = FALSE;
06018 }
06019 }
06020 } end_exprNodeSList_elements;
06021
06022 if (inSwitch)
06023 {
06024 if (!thisReturn || canBreak)
06025 {
06026 mustReturn = FALSE;
06027 }
06028 }
06029
06030 if (isEnumSwitch)
06031 {
06032 if (!hasDefault
06033 && (enumNameSList_size (usedEnums) !=
06034 enumNameList_size (enums)))
06035 {
06036 enumNameSList unused = enumNameSList_subtract (enums, usedEnums);
06037
06038 voptgenerror (FLG_MISSCASE,
06039 message ("Missing case%s in switch: %q",
06040 cstring_makeLiteralTemp
06041 ((enumNameSList_size (unused) > 1) ? "s" : ""),
06042 enumNameSList_unparse (unused)),
06043 g_currentloc);
06044
06045 enumNameSList_free (unused);
06046 }
06047 else
06048 {
06049 hasAllMembers = TRUE;
06050 *allpaths = TRUE;
06051 }
06052
06053 enumNameSList_free (usedEnums);
06054 }
06055 else
06056 {
06057 *allpaths = hasDefault;
06058 }
06059
06060 exprNodeSList_free (el);
06061 return ((hasDefault || hasAllMembers) && mustReturn);
06062 }
06063
06064 exprNode exprNode_switch ( exprNode e, exprNode s)
06065 {
06066 exprNode ret = exprNode_createPartialCopy (e);
06067 bool allpaths;
06068
06069 DPRINTF (("Switch: %s", exprNode_unparse (s)));
06070
06071 ret->kind = XPR_SWITCH;
06072 ret->edata = exprData_makePair (e, s);
06073
06074 if (!exprNode_isError (s))
06075 {
06076 exprNode fs = exprNode_firstStatement (s);
06077 ret->loc = fileloc_update (ret->loc, s->loc);
06078
06079 if (exprNode_isUndefined (fs)
06080 || exprNode_isCaseMarker (fs) || exprNode_isLabelMarker (fs)
06081 || exprNode_isDefaultMarker (fs)) {
06082 ;
06083 } else {
06084 voptgenerror (FLG_FIRSTCASE,
06085 message
06086 ("Statement after switch is not a case: %s", exprNode_unparse (fs)),
06087 fs->loc);
06088 }
06089 }
06090
06091 if (!exprNode_isError (e))
06092 {
06093 if (checkSwitchExpr (e, s, &allpaths))
06094 {
06095 ret->exitCode = XK_MUSTRETURN;
06096 }
06097 else
06098 {
06099 ret->exitCode = e->exitCode;
06100 }
06101
06102 ret->canBreak = e->canBreak;
06103 ret->mustBreak = e->mustBreak;
06104 }
06105
06106
06107
06108
06109 else
06110 {
06111 allpaths = FALSE;
06112 }
06113
06114 DPRINTF (("Context exit switch!"));
06115 context_exitSwitch (ret, allpaths);
06116 DPRINTF (("Context exit switch done!"));
06117
06118 return ret;
06119 }
06120
06121 static void checkInfiniteLoop ( exprNode test,
06122 exprNode body)
06123 {
06124 sRefSet tuses = test->uses;
06125
06126 if (!sRefSet_isEmpty (test->uses))
06127 {
06128 sRefSet sets = sRefSet_newCopy (body->sets);
06129 bool hasError = TRUE;
06130 bool innerState = FALSE;
06131 sRefSet tuncon = sRefSet_undefined;
06132
06133 sets = sRefSet_union (sets, test->sets);
06134 sets = sRefSet_union (sets, body->msets);
06135 sets = sRefSet_union (sets, test->msets);
06136
06137 sRefSet_allElements (tuses, el)
06138 {
06139 if (sRef_isUnconstrained (el))
06140 {
06141 tuncon = sRefSet_insert (tuncon, el);
06142 }
06143 else
06144 {
06145 if (sRefSet_member (sets, el))
06146 {
06147 hasError = FALSE;
06148 break;
06149 }
06150 }
06151
06152 if (sRef_isInternalState (el)
06153 || sRef_isFileStatic (sRef_getRootBase (el)))
06154 {
06155 innerState = TRUE;
06156 }
06157 } end_sRefSet_allElements ;
06158
06159 if (hasError)
06160 {
06161 sRefSet suncon = sRefSet_undefined;
06162 bool sinner = FALSE;
06163
06164 sRefSet_allElements (sets, el)
06165 {
06166 if (sRef_isUnconstrained (el))
06167 {
06168 suncon = sRefSet_insert (suncon, el);
06169 }
06170 else if (sRef_isInternalState (el))
06171 {
06172 sinner = TRUE;
06173 }
06174 else
06175 {
06176 ;
06177 }
06178 } end_sRefSet_allElements ;
06179
06180 if (sinner && innerState)
06181 {
06182 ;
06183 }
06184 else if (sRefSet_isEmpty (tuncon)
06185 && sRefSet_isEmpty (suncon))
06186 {
06187 voptgenerror
06188 (FLG_INFLOOPS,
06189 message
06190 ("Suspected infinite loop. No value used in loop test (%q) "
06191 "is modified by test or loop body.",
06192 sRefSet_unparsePlain (tuses)),
06193 test->loc);
06194 }
06195 else
06196 {
06197 if (sRefSet_isEmpty (tuncon))
06198 {
06199 voptgenerror
06200 (FLG_INFLOOPSUNCON,
06201 message ("Suspected infinite loop. No condition values "
06202 "modified. Modification possible through "
06203 "unconstrained calls: %q",
06204 sRefSet_unparsePlain (suncon)),
06205 test->loc);
06206 }
06207 else
06208 {
06209 voptgenerror
06210 (FLG_INFLOOPSUNCON,
06211 message ("Suspected infinite loop. No condition values "
06212 "modified. Possible undetected dependency through "
06213 "unconstrained calls in loop test: %q",
06214 sRefSet_unparsePlain (tuncon)),
06215 test->loc);
06216 }
06217 }
06218 }
06219
06220 sRefSet_free (sets);
06221 }
06222 }
06223
06224 exprNode exprNode_while ( exprNode t, exprNode b)
06225 {
06226 exprNode ret;
06227 bool emptyErr = FALSE;
06228
06229 if (context_maybeSet (FLG_WHILEEMPTY))
06230 {
06231 if (exprNode_isEmptyStatement (b))
06232 {
06233 emptyErr = optgenerror
06234 (FLG_WHILEEMPTY,
06235 cstring_makeLiteral
06236 ("Body of while statement is empty"),
06237 exprNode_loc (b));
06238 }
06239 }
06240
06241 if (!emptyErr && context_maybeSet (FLG_WHILEBLOCK))
06242 {
06243 if (exprNode_isDefined (b)
06244 && !exprNode_isBlock (b))
06245 {
06246 if (context_inIterDef ()
06247 && (b->kind == XPR_STMTLIST
06248 || b->kind == XPR_TOK))
06249 {
06250 ;
06251 }
06252 else
06253 {
06254 voptgenerror (FLG_WHILEBLOCK,
06255 message
06256 ("Body of while statement is not a block: %s",
06257 exprNode_unparse (b)),
06258 exprNode_loc (b));
06259 }
06260 }
06261 }
06262
06263 if (exprNode_isError (t))
06264 {
06265 if (exprNode_isError (b))
06266 {
06267 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
06268 }
06269 else
06270 {
06271 ret = exprNode_createPartialCopy (b);
06272 }
06273 }
06274 else
06275 {
06276 exprNode test;
06277
06278 ret = exprNode_createPartialCopy (t);
06279
06280 llassert (t->kind == XPR_WHILEPRED);
06281
06282 test = exprData_getSingle (t->edata);
06283
06284 if (!exprNode_isError (b) && exprNode_isDefined (test))
06285 {
06286 if (context_maybeSet (FLG_INFLOOPS)
06287 || context_maybeSet (FLG_INFLOOPSUNCON))
06288 {
06289
06290
06291
06292
06293
06294 checkInfiniteLoop (test, b);
06295 }
06296
06297 exprNode_mergeUSs (ret, b);
06298
06299 if (exprNode_isDefined (b))
06300 {
06301 ret->exitCode = exitkind_makeConditional (b->exitCode);
06302 }
06303 }
06304 }
06305
06306 ret->edata = exprData_makePair (t, b);
06307 ret->kind = XPR_WHILE;
06308
06309 if (exprNode_isDefined (t) && exprNode_mustEscape (t))
06310 {
06311 voptgenerror
06312 (FLG_CONTROL,
06313 message ("Predicate always exits: %s", exprNode_unparse (t)),
06314 exprNode_loc (t));
06315 }
06316
06317 ret->exitCode = XK_NEVERESCAPE;
06318
06319
06320
06321
06322
06323
06324 if (exprNode_knownIntValue (t))
06325 {
06326 if (!exprNode_isZero (t))
06327 {
06328 if (exprNode_isDefined (b))
06329 {
06330 if (!b->canBreak)
06331 {
06332
06333 ret->exitCode = XK_MUSTEXIT;
06334 }
06335 }
06336 }
06337 }
06338 else
06339 {
06340 ;
06341 }
06342
06343 ret->canBreak = FALSE;
06344 ret->mustBreak = FALSE;
06345
06346 return ret;
06347 }
06348
06349
06350
06351
06352
06353
06354
06355 exprNode exprNode_doWhile ( exprNode b, exprNode t)
06356 {
06357 exprNode ret;
06358
06359 if (exprNode_isError (t))
06360 {
06361 if (exprNode_isError (b))
06362 {
06363 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
06364 }
06365 else
06366 {
06367 ret = exprNode_createPartialCopy (b);
06368
06369 ret->exitCode = exitkind_makeConditional (b->exitCode);
06370 exprNode_checkUse (ret, b->sref, b->loc);
06371 ret->exitCode = b->exitCode;
06372 ret->canBreak = b->canBreak;
06373 ret->mustBreak = b->mustBreak;
06374 }
06375 }
06376 else
06377 {
06378 ret = exprNode_createPartialCopy (t);
06379 exprNode_checkPred (cstring_makeLiteralTemp ("while"), t);
06380
06381 if (!exprNode_isError (b))
06382 {
06383
06384
06385
06386
06387 ret->sets = sRefSet_copy (ret->sets, b->sets);
06388 ret->msets = sRefSet_copy (ret->msets, b->msets);
06389 ret->uses = sRefSet_copy (ret->uses, b->uses);
06390
06391
06392
06393
06394 exprNode_checkUse (ret, b->sref, b->loc);
06395 exprNode_mergeUSs (ret, t);
06396 exprNode_checkUse (ret, t->sref, t->loc);
06397
06398 ret->exitCode = b->exitCode;
06399 ret->canBreak = b->canBreak;
06400 ret->mustBreak = b->mustBreak;
06401 }
06402 }
06403
06404 context_exitDoWhileClause (t);
06405
06406 ret->kind = XPR_DOWHILE;
06407 ret->edata = exprData_makePair (t, b);
06408 return ret;
06409 }
06410
06411 exprNode exprNode_for ( exprNode inc, exprNode body)
06412 {
06413 exprNode ret;
06414 bool emptyErr = FALSE;
06415
06416 if (context_maybeSet (FLG_FOREMPTY))
06417 {
06418 if (exprNode_isEmptyStatement (body))
06419 {
06420 emptyErr = optgenerror
06421 (FLG_FOREMPTY,
06422 cstring_makeLiteral
06423 ("Body of for statement is empty"),
06424 exprNode_loc (body));
06425 }
06426 }
06427
06428 if (!emptyErr && context_maybeSet (FLG_FORBLOCK))
06429 {
06430 if (exprNode_isDefined (body)
06431 && !exprNode_isBlock (body))
06432 {
06433 if (context_inIterDef ()
06434 && (body->kind == XPR_STMTLIST
06435 || body->kind == XPR_TOK))
06436 {
06437 ;
06438 }
06439 else
06440 {
06441 voptgenerror (FLG_FORBLOCK,
06442 message
06443 ("Body of for statement is not a block: %s",
06444 exprNode_unparse (body)),
06445 exprNode_loc (body));
06446 }
06447 }
06448 }
06449
06450
06451
06452
06453
06454 if (exprNode_isError (body))
06455 {
06456 ret = exprNode_createPartialCopy (inc);
06457 }
06458 else
06459 {
06460 ret = exprNode_createPartialCopy (body);
06461
06462 ret->exitCode = exitkind_makeConditional (body->exitCode);
06463
06464 exprNode_mergeUSs (inc, body);
06465
06466 if (exprNode_isDefined (inc))
06467 {
06468 exprNode tmp;
06469
06470 context_setMessageAnnote (cstring_makeLiteral ("in post loop increment"));
06471
06472
06473 tmp = exprNode_effect (exprData_getTripleInc (inc->edata));
06474 exprNode_freeShallow (tmp);
06475
06476 context_clearMessageAnnote ();
06477 context_setMessageAnnote (cstring_makeLiteral ("in post loop test"));
06478
06479 tmp = exprNode_effect (exprData_getTripleTest (inc->edata));
06480 exprNode_freeShallow (tmp);
06481
06482 context_clearMessageAnnote ();
06483
06484 ret->uses = sRefSet_copy (ret->uses, inc->uses);
06485 ret->sets = sRefSet_copy (ret->sets, inc->sets);
06486 ret->msets = sRefSet_copy (ret->msets, inc->msets);
06487 }
06488 }
06489
06490 ret->kind = XPR_FOR;
06491 ret->edata = exprData_makePair (inc, body);
06492
06493 if (exprNode_isDefined (inc)) {
06494 exprNode test = exprData_getTripleTest (inc->edata);
06495
06496 if (exprNode_isUndefined (test)) {
06497 if (exprNode_isDefined (body)) {
06498 if (!body->canBreak) {
06499
06500 ret->exitCode = XK_MUSTEXIT;
06501 }
06502 }
06503 }
06504 }
06505
06506 return (ret);
06507 }
06508
06509
06510
06511
06512
06513
06514
06515
06516
06517
06518
06519
06520 guardSet exprNode_getForGuards (exprNode pred)
06521 {
06522 exprNode test;
06523
06524 if (exprNode_isError (pred)) return guardSet_undefined;
06525
06526 llassert (pred->kind == XPR_FORPRED);
06527
06528 test = exprData_getTripleTest (pred->edata);
06529
06530 if (!exprNode_isError (test))
06531 {
06532 return (test->guards);
06533 }
06534
06535 return guardSet_undefined;
06536 }
06537
06538 exprNode exprNode_whilePred ( exprNode test)
06539 {
06540 exprNode ret = exprNode_createSemiCopy (test);
06541
06542 if (exprNode_isDefined (test))
06543 {
06544 exprNode_copySets (ret, test);
06545 exprNode_checkPred (cstring_makeLiteralTemp ("while"), test);
06546 exprNode_checkUse (ret, test->sref, test->loc);
06547
06548 exprNode_produceGuards (test);
06549
06550 ret->guards = guardSet_copy (test->guards);
06551 }
06552
06553 ret->edata = exprData_makeSingle (test);
06554 ret->kind = XPR_WHILEPRED;
06555 return ret;
06556 }
06557
06558 exprNode exprNode_forPred ( exprNode init, exprNode test,
06559 exprNode inc)
06560 {
06561 exprNode ret;
06562
06563
06564
06565
06566
06567 exprNode_checkPred (cstring_makeLiteralTemp ("for"), test);
06568
06569 if (!exprNode_isError (inc))
06570 {
06571 ret = exprNode_createPartialCopy (inc);
06572 }
06573 else
06574 {
06575 if (!exprNode_isError (init))
06576 {
06577 ret = exprNode_createPartialCopy (init);
06578 }
06579 else if (!exprNode_isError (test))
06580 {
06581 ret = exprNode_createPartialCopy (test);
06582 }
06583 else
06584 {
06585 ret = exprNode_createUnknown ();
06586 }
06587 }
06588
06589 exprNode_mergeUSs (ret, init);
06590
06591 if (exprNode_isDefined (init))
06592 {
06593 exprNode_checkUse (ret, init->sref, init->loc);
06594 }
06595
06596 exprNode_mergeUSs (ret, test);
06597
06598 if (exprNode_isDefined (test))
06599 {
06600 exprNode_checkUse (ret, test->sref, test->loc);
06601 }
06602
06603 ret->kind = XPR_FORPRED;
06604 ret->edata = exprData_makeFor (init, test, inc);
06605 return (ret);
06606 }
06607
06608 exprNode exprNode_goto ( cstring label)
06609 {
06610 exprNode ret = exprNode_createUnknown ();
06611
06612 if (context_inMacro ())
06613 {
06614 voptgenerror (FLG_MACROSTMT,
06615 message ("Macro %s uses goto (not functional)",
06616 context_inFunctionName ()),
06617 g_currentloc);
06618 }
06619
06620 ret->kind = XPR_GOTO;
06621 ret->edata = exprData_makeLiteral (label);
06622 ret->mustBreak = TRUE;
06623 ret->exitCode = XK_GOTO;
06624 ret->canBreak = TRUE;
06625 return ret;
06626 }
06627
06628 exprNode exprNode_continue ( lltok l, int qcontinue)
06629 {
06630 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
06631
06632 ret->kind = XPR_CONTINUE;
06633 ret->edata = exprData_makeTok (l);
06634 ret->canBreak = TRUE;
06635 ret->mustBreak = TRUE;
06636
06637 if (qcontinue == QSAFEBREAK)
06638 {
06639 ;
06640 }
06641 else if (qcontinue == QINNERCONTINUE)
06642 {
06643 if (!context_inDeepLoop ())
06644 {
06645 voptgenerror
06646 (FLG_LOOPLOOPCONTINUE,
06647 cstring_makeLiteral ("Continue statement marked with innercontinue "
06648 "is not inside a nested loop"),
06649 exprNode_loc (ret));
06650 }
06651 }
06652 else if (qcontinue == BADTOK)
06653 {
06654 if (context_inDeepLoop ())
06655 {
06656 voptgenerror
06657 (FLG_LOOPLOOPCONTINUE,
06658 cstring_makeLiteral ("Continue statement in nested loop"),
06659 exprNode_loc (ret));
06660 }
06661 }
06662 else
06663 {
06664 llbuglit ("exprNode_continue: bad qcontinue");
06665 }
06666
06667 return ret;
06668 }
06669
06670 exprNode exprNode_break ( lltok l, int bqual)
06671 {
06672 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
06673 clause breakClause = context_breakClause ();
06674
06675 ret->kind = XPR_BREAK;
06676 ret->edata = exprData_makeTok (l);
06677 ret->canBreak = TRUE;
06678 ret->mustBreak = TRUE;
06679
06680 if (breakClause == NOCLAUSE)
06681 {
06682 voptgenerror
06683 (FLG_SYNTAX,
06684 cstring_makeLiteral ("Break not inside while, for or switch statement"),
06685 exprNode_loc (ret));
06686 }
06687 else
06688 {
06689 if (bqual != BADTOK)
06690 {
06691 switch (bqual)
06692 {
06693 case QSAFEBREAK:
06694 break;
06695 case QINNERBREAK:
06696 if (breakClause == SWITCHCLAUSE)
06697 {
06698 if (!context_inDeepSwitch ())
06699 {
06700 voptgenerror (FLG_SYNTAX,
06701 cstring_makeLiteral
06702 ("Break preceded by innerbreak is not in a deep switch"),
06703 exprNode_loc (ret));
06704 }
06705 }
06706 else
06707 {
06708 if (!context_inDeepLoop ())
06709 {
06710 voptgenerror (FLG_SYNTAX,
06711 cstring_makeLiteral
06712 ("Break preceded by innerbreak is not in a deep loop"),
06713 exprNode_loc (ret));
06714 }
06715 }
06716 break;
06717 case QLOOPBREAK:
06718 if (breakClause == SWITCHCLAUSE)
06719 {
06720 voptgenerror (FLG_SYNTAX,
06721 cstring_makeLiteral
06722 ("Break preceded by loopbreak is breaking a switch"),
06723 exprNode_loc (ret));
06724 }
06725 break;
06726 case QSWITCHBREAK:
06727 if (breakClause != SWITCHCLAUSE)
06728 {
06729 voptgenerror
06730 (FLG_SYNTAX,
06731 message ("Break preceded by switchbreak is breaking %s",
06732 cstring_makeLiteralTemp
06733 ((breakClause == WHILECLAUSE
06734 || breakClause == DOWHILECLAUSE) ? "a while loop"
06735 : (breakClause == FORCLAUSE) ? "a for loop"
06736 : (breakClause == ITERCLAUSE) ? "an iterator"
06737 : "<error loop>")),
06738 exprNode_loc (ret));
06739 }
06740 break;
06741 BADDEFAULT;
06742 }
06743 }
06744 else
06745 {
06746 if (breakClause == SWITCHCLAUSE)
06747 {
06748 clause nextBreakClause = context_nextBreakClause ();
06749
06750 switch (nextBreakClause)
06751 {
06752 case NOCLAUSE: break;
06753 case WHILECLAUSE:
06754 case DOWHILECLAUSE:
06755 case FORCLAUSE:
06756 case ITERCLAUSE:
06757 voptgenerror
06758 (FLG_LOOPSWITCHBREAK,
06759 cstring_makeLiteral ("Break statement in switch inside loop"),
06760 exprNode_loc (ret));
06761 break;
06762 case SWITCHCLAUSE:
06763 voptgenerror
06764 (FLG_SWITCHSWITCHBREAK,
06765 cstring_makeLiteral ("Break statement in switch inside switch"),
06766 exprNode_loc (ret));
06767 break;
06768 BADDEFAULT;
06769 }
06770 }
06771 else
06772 {
06773 if (context_inDeepLoop ())
06774 {
06775 voptgenerror
06776 (FLG_LOOPLOOPBREAK,
06777 cstring_makeLiteral ("Break statement in nested loop"),
06778 exprNode_loc (ret));
06779 }
06780 else
06781 {
06782 if (context_inDeepLoopSwitch ())
06783 {
06784 voptgenerror
06785 (FLG_SWITCHLOOPBREAK,
06786 cstring_makeLiteral ("Break statement in loop inside switch"),
06787 exprNode_loc (ret));
06788 }
06789 }
06790 }
06791 }
06792 }
06793
06794 return ret;
06795 }
06796
06797 exprNode exprNode_nullReturn ( lltok t)
06798 {
06799 fileloc loc = lltok_getLoc (t);
06800 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
06801
06802 context_returnFunction ();
06803 exprChecks_checkNullReturn (loc);
06804
06805 ret->kind = XPR_NULLRETURN;
06806 ret->edata = exprData_makeTok (t);
06807 ret->exitCode = XK_MUSTRETURN;
06808 return ret;
06809 }
06810
06811 exprNode exprNode_return ( exprNode e)
06812 {
06813 exprNode ret;
06814
06815 if (exprNode_isError (e))
06816 {
06817 ret = exprNode_createUnknown ();
06818 }
06819 else
06820 {
06821 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (e->loc));
06822
06823 exprNode_checkUse (ret, e->sref, e->loc);
06824 exprNode_checkReturn (e);
06825 }
06826
06827 context_returnFunction ();
06828 ret->kind = XPR_RETURN;
06829 ret->edata = exprData_makeSingle (e);
06830 ret->exitCode = XK_MUSTRETURN;
06831
06832 return (ret);
06833 }
06834
06835 exprNode exprNode_comma ( exprNode e1, exprNode e2)
06836 {
06837 exprNode ret;
06838
06839 if (exprNode_isError (e1))
06840 {
06841 if (exprNode_isError (e2))
06842 {
06843 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
06844 }
06845 else
06846 {
06847 ret = exprNode_createPartialCopy (e2);
06848 exprNode_checkUse (ret, e2->sref, e2->loc);
06849 ret->sref = e2->sref;
06850 }
06851 }
06852 else
06853 {
06854 ret = exprNode_createPartialCopy (e1);
06855
06856 exprNode_checkUse (ret, e1->sref, e1->loc);
06857
06858 if (!exprNode_isError (e2))
06859 {
06860 exprNode_mergeUSs (ret, e2);
06861 exprNode_checkUse (ret, e2->sref, e2->loc);
06862 ret->sref = e2->sref;
06863 }
06864 }
06865
06866 ret->kind = XPR_COMMA;
06867 ret->edata = exprData_makePair (e1, e2);
06868
06869 if (exprNode_isDefined (e1))
06870 {
06871 if (exprNode_isDefined (e2))
06872 {
06873 ret->typ = e2->typ;
06874
06875 if (exprNode_mustEscape (e1) || e1->mustBreak)
06876 {
06877 voptgenerror
06878 (FLG_UNREACHABLE,
06879 message ("Second clause of comma expression is unreachable: %s",
06880 exprNode_unparse (e2)),
06881 exprNode_loc (e2));
06882 }
06883
06884 ret->exitCode = exitkind_combine (e1->exitCode, e2->exitCode);
06885 ret->mustBreak = e1->mustBreak || e2->mustBreak;
06886 ret->canBreak = e1->canBreak || e2->canBreak;
06887 }
06888 else
06889 {
06890 if (exprNode_mustEscape (e1) || e1->mustBreak)
06891 {
06892 voptgenerror
06893 (FLG_UNREACHABLE,
06894 message ("Second clause of comma expression is unreachable: %s",
06895 exprNode_unparse (e2)),
06896 exprNode_loc (e2));
06897 }
06898
06899 ret->exitCode = e1->exitCode;
06900 ret->canBreak = e1->canBreak;
06901 }
06902 }
06903 else
06904 {
06905 if (exprNode_isDefined (e2))
06906 {
06907 ret->exitCode = e2->exitCode;
06908 ret->mustBreak = e2->mustBreak;
06909 ret->canBreak = e2->canBreak;
06910 }
06911 }
06912
06913 return (ret);
06914 }
06915
06916 static bool exprNode_checkOneInit ( exprNode el, exprNode val)
06917 {
06918 ctype t1 = exprNode_getType (el);
06919 ctype t2 = exprNode_getType (val);
06920 bool hasError = FALSE;
06921
06922 if (ctype_isUnknown (t1))
06923 {
06924 voptgenerror (FLG_IMPTYPE,
06925 message ("Variable has unknown (implicitly int) type: %s",
06926 exprNode_unparse (el)),
06927 el->loc);
06928
06929 t1 = ctype_int;
06930 el->typ = ctype_int;
06931 }
06932
06933 if (exprNode_isDefined (val) && val->kind == XPR_INITBLOCK)
06934 {
06935 exprNodeList vals = exprData_getArgs (val->edata);
06936
06937 if (ctype_isRealAP (t1))
06938 {
06939 int i = 0;
06940 int nerrors = 0;
06941
06942 exprNodeList_elements (vals, oneval)
06943 {
06944 cstring istring = message ("%d", i);
06945 exprNode newel =
06946 exprNode_arrayFetch
06947 (exprNode_fakeCopy (el),
06948 exprNode_numLiteral (ctype_int, istring,
06949 fileloc_copy (el->loc), i));
06950
06951 if (exprNode_isDefined (newel))
06952 {
06953 if (exprNodeList_size (vals) == 1
06954 && ctype_isString (exprNode_getType (oneval))
06955 && ctype_isChar (exprNode_getType (newel)))
06956 {
06957 exprNode_freeIniter (newel);
06958 }
06959 else
06960 {
06961 if (exprNode_checkOneInit (newel, oneval))
06962 {
06963 hasError = TRUE;
06964 nerrors++;
06965
06966 if (nerrors > 3 && exprNodeList_size (vals) > 6)
06967 {
06968 llgenmsg
06969 (message ("Additional initialization errors "
06970 "for %s not reported",
06971 exprNode_unparse (el)),
06972 exprNode_loc (el));
06973 exprNode_freeIniter (newel);
06974 break;
06975 }
06976 else
06977 {
06978 exprNode_freeIniter (newel);
06979 }
06980 }
06981 else
06982 {
06983 exprNode_freeIniter (newel);
06984 }
06985 }
06986 }
06987
06988 cstring_free (istring);
06989 i++;
06990
06991 } end_exprNodeList_elements;
06992
06993 }
06994 else if (ctype_isStruct (ctype_realType (t1)))
06995 {
06996 uentryList fields = ctype_getFields (t1);
06997 int i = 0;
06998
06999 if (uentryList_size (fields) != exprNodeList_size (vals))
07000 {
07001 if (uentryList_size (fields) > exprNodeList_size (vals))
07002 {
07003 hasError = optgenerror
07004 (FLG_FULLINITBLOCK,
07005 message ("Initializer block for "
07006 "%s has %d field%p, but %s has %d field%p: %q",
07007 exprNode_unparse (el),
07008 exprNodeList_size (vals),
07009 ctype_unparse (t1),
07010 uentryList_size (fields),
07011 exprNodeList_unparse (vals)),
07012 val->loc);
07013 }
07014 else
07015 {
07016 hasError = optgenerror
07017 (FLG_TYPE,
07018 message ("Initializer block for "
07019 "%s has %d field%p, but %s has %d field%p: %q",
07020 exprNode_unparse (el),
07021 exprNodeList_size (vals),
07022 ctype_unparse (t1),
07023 uentryList_size (fields),
07024 exprNodeList_unparse (vals)),
07025 val->loc);
07026 }
07027 }
07028 else
07029 {
07030 exprNodeList_elements (vals, oneval)
07031 {
07032 uentry thisfield = uentryList_getN (fields, i);
07033 exprNode newel =
07034 exprNode_fieldAccess (exprNode_fakeCopy (el),
07035 uentry_getName (thisfield));
07036
07037 if (exprNode_isDefined (newel))
07038 {
07039 if (exprNode_checkOneInit (newel, oneval))
07040 {
07041 hasError = TRUE;
07042 }
07043
07044 exprNode_freeIniter (newel);
07045 }
07046
07047 i++;
07048 } end_exprNodeList_elements;
07049 }
07050 }
07051 else
07052 {
07053 hasError = optgenerror
07054 (FLG_TYPE,
07055 message ("Initializer block used for "
07056 "%s where %t is expected: %s",
07057 exprNode_unparse (el), t1, exprNode_unparse (val)),
07058 val->loc);
07059 }
07060 }
07061 else
07062 {
07063 if (exprNode_isDefined (val))
07064 {
07065 doAssign (el, val, TRUE);
07066
07067 if (!exprNode_matchType (t1, val))
07068 {
07069 hasError = gentypeerror
07070 (t1, val, t2, el,
07071 message ("Initial value of %s is type %t, "
07072 "expects %t: %s",
07073 exprNode_unparse (el),
07074 t2, t1, exprNode_unparse (val)),
07075 val->loc);
07076 }
07077 }
07078 }
07079
07080 return hasError;
07081 }
07082
07083 exprNode exprNode_makeInitialization ( idDecl t,
07084 exprNode e)
07085 {
07086 uentry ue = usymtab_lookup (idDecl_observeId (t));
07087 bool isUsed = uentry_isUsed (ue);
07088 exprNode ret = exprNode_fromIdentifierAux (ue);
07089 ctype ct = ctype_realishType (ret->typ);
07090 fileloc loc;
07091
07092 if (ctype_isUnknown (ct))
07093 {
07094 voptgenerror (FLG_IMPTYPE,
07095 message ("Variable has unknown (implicitly int) type: %s",
07096 idDecl_getName (t)),
07097 exprNode_isDefined (e) ? exprNode_loc (e) : g_currentloc);
07098
07099 ct = ctype_int;
07100 }
07101
07102 if (exprNode_isError (e))
07103 {
07104 e = exprNode_createUnknown ();
07105 loc = g_currentloc;
07106
07107
07108 sRef_setDefined (ret->sref, loc);
07109 }
07110 else
07111 {
07112 loc = exprNode_loc (e);
07113
07114
07115
07116
07117
07118
07119
07120
07121
07122 exprNode_checkUse (ret, e->sref, e->loc);
07123
07124 if (ctype_isUnknown (e->typ) && uentry_isValid (ue))
07125 {
07126 exprNode lhs = exprNode_createId (ue);
07127
07128
07129
07130
07131
07132 if (uentry_isStatic (ue))
07133 {
07134 sRef_setDefState (lhs->sref, SS_PARTIAL, fileloc_undefined);
07135 }
07136
07137 (void) exprNode_checkOneInit (lhs, e);
07138
07139 if (uentry_isStatic (ue))
07140 {
07141 sRef_setDefState (lhs->sref, SS_DEFINED, fileloc_undefined);
07142 }
07143
07144 exprNode_free (lhs);
07145 }
07146 else
07147 {
07148 if (!exprNode_matchType (ct, e))
07149 {
07150 if (exprNode_isZero (e) && ctype_isArrayPtr (ct))
07151 {
07152 ;
07153 }
07154 else
07155 {
07156 (void) gentypeerror
07157 (exprNode_getType (e), e, exprNode_getType (ret), ret,
07158 message
07159 ("Variable %s initialized to type %t, expects %t: %s",
07160 exprNode_unparse (ret), exprNode_getType (e),
07161 exprNode_getType (ret),
07162 exprNode_unparse (e)),
07163 e->loc);
07164 }
07165 }
07166 }
07167
07168 if (uentry_isStatic (ue))
07169 {
07170 sRef_setDefState (ret->sref, SS_PARTIAL, fileloc_undefined);
07171 }
07172
07173 doAssign (ret, e, TRUE);
07174
07175 if (uentry_isStatic (ue))
07176 {
07177 sRef_setDefState (ret->sref, SS_DEFINED, fileloc_undefined);
07178 }
07179 }
07180
07181 if (context_inIterDef ())
07182 {
07183
07184 uentry_setUsed (ue, loc);
07185 }
07186 else
07187 {
07188 if (!isUsed)
07189 {
07190 uentry_setNotUsed (ue);
07191 }
07192 }
07193
07194 ret->exitCode = XK_NEVERESCAPE;
07195 ret->mustBreak = FALSE;
07196
07197
07198
07199
07200
07201 exprData_free (ret->edata, ret->kind);
07202
07203 ret->kind = XPR_INIT;
07204 ret->edata = exprData_makeInit (t, e);
07205 exprNode_mergeUSs (ret, e);
07206 return ret;
07207 }
07208
07209 exprNode exprNode_iter ( uentry name,
07210 exprNodeList alist,
07211 exprNode body,
07212 uentry end)
07213 {
07214 exprNode ret;
07215 cstring iname;
07216
07217 llassert (uentry_isValid (name));
07218
07219 uentry_setUsed (name, exprNode_loc (body));
07220
07221 ret = exprNode_createPartialCopy (body);
07222 iname = uentry_getName (name);
07223
07224 if (uentry_isInvalid (end))
07225 {
07226 llerror (FLG_ITER,
07227 message ("Iter %s not balanced with end_%s", iname, iname));
07228 }
07229 else
07230 {
07231 cstring ename = uentry_getName (end);
07232
07233 if (!cstring_equalPrefix (ename, "end_"))
07234 {
07235 llerror (FLG_ITER, message ("Iter %s not balanced with end_%s: %s",
07236 iname, iname, ename));
07237 }
07238 else
07239 {
07240 if (!cstring_equal (iname, cstring_suffix (ename, 4)))
07241 {
07242 llerror (FLG_ITER,
07243 message ("Iter %s not balanced with end_%s: %s",
07244 iname, iname, ename));
07245 }
07246 }
07247
07248 cstring_free (ename);
07249 }
07250
07251 context_exitIterClause (body);
07252
07253 ret->kind = XPR_ITER;
07254 ret->edata = exprData_makeIter (name, alist, body, end);
07255
07256 if (uentry_isIter (name))
07257 {
07258 (void) checkArgsReal (name, body,
07259 uentry_getParams (name), alist, TRUE, ret);
07260 }
07261
07262 cstring_free (iname);
07263
07264 return ret;
07265 }
07266
07267 exprNode
07268 exprNode_iterNewId ( cstring s)
07269 {
07270 exprNode e = exprNode_new ();
07271 uentry ue = uentryList_getN (uentry_getParams (getCurrentIter ()), iterParamNo ());
07272
07273 llassert (processingIterVars ());
07274
07275 e->loc = context_getSaveLocation ();
07276
07277 if (fileloc_isUndefined (e->loc))
07278 {
07279 fileloc_free (e->loc);
07280 e->loc = fileloc_copy (g_currentloc);
07281 }
07282
07283 e->uses = sRefSet_new ();
07284 e->sets = sRefSet_new ();
07285 e->msets = sRefSet_new ();
07286 e->kind = XPR_VAR;
07287 e->val = multiVal_unknown ();
07288 e->guards = guardSet_new ();
07289 e->sref = defref;
07290 e->isJumpPoint = FALSE;
07291 e->exitCode = XK_NEVERESCAPE;
07292
07293
07294 e->canBreak = FALSE;
07295 e->mustBreak = FALSE;
07296 e->etext = cstring_undefined;
07297
07298 if (uentry_isYield (ue))
07299 {
07300 uentry uue = uentry_makeVariable (s, uentry_getType (ue),
07301 fileloc_copy (e->loc),
07302 FALSE);
07303 sRef sr;
07304
07305 uue = usymtab_supEntrySrefReturn (uue);
07306
07307 sr = uentry_getSref (uue);
07308 sRef_mergeStateQuiet (sr, uentry_getSref (ue));
07309 sr = uentry_getSref (uue);
07310 sRef_setDefined (sr, e->loc);
07311
07312 e->typ = uentry_getType (uue);
07313 e->sref = sr;
07314 e->edata = exprData_makeId (uue);
07315 uentry_setUsed (uue, g_currentloc);
07316 }
07317 else
07318 {
07319 uentry uue;
07320
07321 sRef_setGlobalScope ();
07322 uue = uentry_makeVariableLoc (s, ctype_unknown);
07323
07324 e->typ = ctype_unknown;
07325 e->edata = exprData_makeId (uue);
07326
07327 uentry_setUsed (uue, e->loc);
07328 uentry_setHasNameError (uue);
07329
07330 if (context_getFlag (FLG_REPEATUNRECOG))
07331 {
07332 uentry_markOwned (uue);
07333 }
07334 else
07335 {
07336 usymtab_supGlobalEntry (uue);
07337 }
07338
07339 sRef_clearGlobalScope ();
07340
07341 voptgenerror (FLG_UNRECOG, message ("Unrecognized identifier: %s", s),
07342 e->loc);
07343 }
07344
07345
07346 cstring_free (s);
07347 return (e);
07348 }
07349
07350 exprNode
07351 exprNode_iterExpr ( exprNode e)
07352 {
07353 if (!processingIterVars ())
07354 {
07355 llcontbuglit ("checkIterParam: not in iter");
07356 return e;
07357 }
07358
07359 if (uentry_isYield (uentryList_getN (uentry_getParams (getCurrentIter ()),
07360 iterParamNo ())))
07361 {
07362 if (exprNode_isDefined (e))
07363 {
07364 if (fileloc_isDefined (e->loc))
07365 {
07366 voptgenerror
07367 (FLG_ITER,
07368 message ("Yield parameter is not simple identifier: %s",
07369 exprNode_unparse (e)),
07370 e->loc);
07371 }
07372 else
07373 {
07374 voptgenerror
07375 (FLG_ITER,
07376 message ("Yield parameter is not simple identifier: %s",
07377 exprNode_unparse (e)),
07378 g_currentloc);
07379
07380 }
07381 }
07382 }
07383 return e;
07384 }
07385
07386 exprNode
07387 exprNode_iterId ( uentry c)
07388 {
07389 uentry ue;
07390
07391 llassert (processingIterVars ());
07392
07393 ue = uentryList_getN (uentry_getParams (getCurrentIter ()),
07394 iterParamNo ());
07395
07396 if (uentry_isYield (ue))
07397 {
07398 ctype ct = uentry_getType (ue);
07399 exprNode e = exprNode_createPlain (ct);
07400 cstring name = uentry_getName (c);
07401 uentry le = uentry_makeVariable (name, ct, fileloc_undefined, FALSE);
07402
07403 uentry_setUsed (ue, g_currentloc);
07404 uentry_setHasNameError (ue);
07405
07406 cstring_free (name);
07407
07408 e->kind = XPR_VAR;
07409 e->edata = exprData_makeId (le);
07410 e->loc = context_getSaveLocation ();
07411 e->sref = uentry_getSref (le);
07412
07413 usymtab_supEntrySref (le);
07414
07415 if (!context_inHeader ())
07416 {
07417 if (optgenerror
07418 (FLG_ITER,
07419 message ("Yield parameter shadows local declaration: %q",
07420 uentry_getName (c)),
07421 fileloc_isDefined (e->loc) ? e->loc : g_currentloc))
07422 {
07423 uentry_showWhereDeclared (c);
07424 }
07425 }
07426
07427 return e;
07428 }
07429
07430 return (exprNode_fromIdentifierAux (c));
07431 }
07432
07433 exprNode exprNode_iterStart ( uentry name, exprNodeList alist)
07434 {
07435 exprNode ret = exprNode_create (ctype_unknown);
07436
07437 ret->kind = XPR_ITERCALL;
07438 ret->edata = exprData_makeIterCall (name, alist);
07439
07440 if (uentry_isIter (name))
07441 {
07442 uentryList params = uentry_getParams (name);
07443
07444 if (context_inIterDef ()
07445 && uentryList_size (params) == exprNodeList_size (alist))
07446 {
07447 int i = 0;
07448
07449 exprNodeList_elements (alist, arg)
07450 {
07451 uentry parg = uentryList_getN (params, i);
07452
07453 if (uentry_isYield (parg))
07454 {
07455 uentry ue = exprNode_getUentry (arg);
07456
07457 if (uentry_isValid (ue))
07458 {
07459 ;
07460 }
07461 }
07462
07463 i++;
07464 } end_exprNodeList_elements;
07465 }
07466
07467 (void) checkArgsReal (name, ret, params, alist, TRUE, ret);
07468 checkUnspecCall (ret, params, alist);
07469 }
07470
07471 return ret;
07472 }
07473
07474 sRef exprNode_getSref (exprNode e)
07475 {
07476 if (exprNode_isDefined (e))
07477 {
07478
07479 if (e->sref == defref)
07480 {
07481
07482 e->sref = sRef_makeUnknown ();
07483 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
07484
07485 return e->sref;
07486 }
07487 else
07488 {
07489 return e->sref;
07490 }
07491 }
07492 else
07493 {
07494 return sRef_undefined;
07495 }
07496 }
07497
07498 cstring
07499 exprNode_unparseFirst (exprNode e)
07500 {
07501 if (exprNode_isDefined (e))
07502 {
07503 cstring ret;
07504
07505 if (e->kind == XPR_STMTLIST
07506 || e->kind == XPR_COMMA || e->kind == XPR_COND)
07507 {
07508 exprNode first = exprData_getPairA (e->edata);
07509
07510 if (exprNode_isDefined (first))
07511 {
07512 return (exprNode_unparseFirst (exprData_getPairA (e->edata)));
07513 }
07514 else
07515 {
07516 return (cstring_makeLiteralTemp ("..."));
07517 }
07518 }
07519
07520 ret = cstring_elide (exprNode_unparse (e), 20);
07521 cstring_markOwned (ret);
07522
07523 return (ret);
07524 }
07525 else
07526 {
07527 return cstring_makeLiteralTemp ("<error>");
07528 }
07529 }
07530
07531 cstring
07532 exprNode_unparse (exprNode e)
07533 {
07534 if (exprNode_isError (e))
07535 {
07536 return cstring_makeLiteralTemp ("<error>");
07537 }
07538
07539 if (cstring_isDefined (e->etext))
07540 {
07541 return e->etext;
07542 }
07543 else
07544 {
07545 cstring ret = exprNode_doUnparse (e);
07546
07547
07548 e->etext = ret;
07549
07550 return ret;
07551 }
07552 }
07553
07554 fileloc
07555 exprNode_loc (exprNode e)
07556 {
07557 if (exprNode_isError (e))
07558 {
07559 return (g_currentloc);
07560 }
07561 else
07562 {
07563 return (e->loc);
07564 }
07565 }
07566
07567
07568
07569
07570
07571
07572
07573 static exprNodeList exprNodeList_effect (exprNodeList e)
07574 {
07575 exprNodeList ret = exprNodeList_new ();
07576
07577 exprNodeList_elements (e, current)
07578 {
07579 exprNodeList_addh (ret, exprNode_effect (current));
07580 } end_exprNodeList_elements;
07581
07582 return ret;
07583 }
07584
07585 static exprNode exprNode_effect (exprNode e)
07586
07587 {
07588 bool innerEffect = inEffect;
07589 exprNode ret;
07590 exprData data;
07591
07592 inEffect = TRUE;
07593
07594 context_clearJustPopped ();
07595
07596 if (exprNode_isError (e))
07597 {
07598 ret = exprNode_undefined;
07599 }
07600 else
07601 {
07602
07603
07604
07605
07606
07607
07608
07609
07610
07611
07612
07613
07614 data = e->edata;
07615
07616 switch (e->kind)
07617 {
07618 case XPR_PARENS:
07619 ret = exprNode_addParens (exprData_getUopTok (data),
07620 exprNode_effect (exprData_getUopNode (data)));
07621 break;
07622 case XPR_ASSIGN:
07623 ret = exprNode_assign (exprNode_effect (exprData_getOpA (data)),
07624 exprNode_effect (exprData_getOpB (data)),
07625 exprData_getOpTok (data));
07626 break;
07627 case XPR_INITBLOCK:
07628 ret = exprNode_undefined;
07629 break;
07630 case XPR_CALL:
07631 ret = exprNode_functionCall (exprNode_effect (exprData_getFcn (data)),
07632 exprNodeList_effect (exprData_getArgs (data)));
07633 break;
07634 case XPR_EMPTY:
07635 ret = e;
07636 break;
07637
07638 case XPR_LABEL:
07639 ret = e;
07640 break;
07641
07642 case XPR_CONST:
07643 case XPR_VAR:
07644 {
07645 cstring id = exprData_getId (data);
07646 uentry ue = usymtab_lookupSafe (id);
07647
07648 ret = exprNode_fromIdentifierAux (ue);
07649 ret->loc = fileloc_update (ret->loc, e->loc);
07650 break;
07651 }
07652 case XPR_BODY:
07653 ret = e;
07654 break;
07655 case XPR_FETCH:
07656 ret = exprNode_arrayFetch (exprNode_effect (exprData_getPairA (data)),
07657 exprNode_effect (exprData_getPairB (data)));
07658 break;
07659 case XPR_OP:
07660 ret = exprNode_op (exprNode_effect (exprData_getOpA (data)),
07661 exprNode_effect (exprData_getOpB (data)),
07662 exprData_getOpTok (data));
07663 break;
07664
07665 case XPR_POSTOP:
07666 ret = exprNode_postOp (exprNode_effect (exprData_getUopNode (data)),
07667 exprData_getUopTok (data));
07668 break;
07669 case XPR_PREOP:
07670 ret = exprNode_preOp (exprNode_effect (exprData_getUopNode (data)),
07671 exprData_getUopTok (data));
07672 break;
07673
07674 case XPR_OFFSETOF:
07675 case XPR_SIZEOFT:
07676 case XPR_SIZEOF:
07677 case XPR_ALIGNOFT:
07678 case XPR_ALIGNOF:
07679 ret = e;
07680 break;
07681
07682 case XPR_VAARG:
07683 ret = exprNode_vaArg (exprData_getCastTok (data),
07684 exprNode_effect (exprData_getCastNode (data)),
07685 exprData_getCastType (data));
07686 break;
07687
07688 case XPR_CAST:
07689 ret = exprNode_cast (exprData_getCastTok (data),
07690 exprNode_effect (exprData_getCastNode (data)),
07691 exprData_getCastType (data));
07692 break;
07693 case XPR_ITERCALL:
07694 ret = exprNode_iterStart (exprData_getIterCallIter (data),
07695 exprNodeList_effect
07696 (exprData_getIterCallArgs (data)));
07697 break;
07698
07699 case XPR_ITER:
07700 ret = exprNode_iter (exprData_getIterSname (data),
07701 exprNodeList_effect (exprData_getIterAlist (data)),
07702 exprNode_effect (exprData_getIterBody (data)),
07703 exprData_getIterEname (data));
07704 break;
07705
07706 case XPR_FOR:
07707 ret = exprNode_for (exprNode_effect (exprData_getPairA (data)),
07708 exprNode_effect (exprData_getPairB (data)));
07709 break;
07710
07711 case XPR_FORPRED:
07712 ret = exprNode_forPred (exprNode_effect (exprData_getTripleInit (data)),
07713 exprNode_effect (exprData_getTripleTest (data)),
07714 exprNode_effect (exprData_getTripleInc (data)));
07715 break;
07716
07717 case XPR_TOK:
07718 ret = exprNode_createTok (exprData_getTok (data));
07719 break;
07720
07721 case XPR_GOTO:
07722 ret = exprNode_goto (exprData_getLiteral (data));
07723 ret->loc = fileloc_update (ret->loc, e->loc);
07724 break;
07725
07726 case XPR_CONTINUE:
07727 ret = exprNode_continue (exprData_getTok (data), QSAFEBREAK);
07728 break;
07729
07730 case XPR_BREAK:
07731 ret = exprNode_break (exprData_getTok (data), QSAFEBREAK);
07732 break;
07733
07734 case XPR_RETURN:
07735 ret = exprNode_return (exprNode_effect (exprData_getSingle (data)));
07736 break;
07737
07738 case XPR_NULLRETURN:
07739 ret = exprNode_nullReturn (exprData_getTok (data));
07740 break;
07741
07742 case XPR_COMMA:
07743 ret = exprNode_comma (exprNode_effect (exprData_getPairA (data)),
07744 exprNode_effect (exprData_getPairB (data)));
07745 break;
07746
07747 case XPR_COND:
07748 ret = exprNode_cond (exprNode_effect (exprData_getTriplePred (data)),
07749 exprNode_effect (exprData_getTripleTrue (data)),
07750 exprNode_effect (exprData_getTripleFalse (data)));
07751 break;
07752 case XPR_IF:
07753 ret = exprNode_if (exprNode_effect (exprData_getPairA (data)),
07754 exprNode_effect (exprData_getPairB (data)));
07755 break;
07756
07757 case XPR_IFELSE:
07758 ret = exprNode_ifelse (exprNode_effect (exprData_getTriplePred (data)),
07759 exprNode_effect (exprData_getTripleTrue (data)),
07760 exprNode_effect (exprData_getTripleFalse (data)));
07761 break;
07762 case XPR_WHILEPRED:
07763 ret = exprNode_whilePred (exprData_getSingle (data));
07764 break;
07765
07766 case XPR_WHILE:
07767 ret = exprNode_while (exprNode_effect (exprData_getPairA (data)),
07768 exprNode_effect (exprData_getPairB (data)));
07769 break;
07770
07771 case XPR_DOWHILE:
07772 ret = exprNode_doWhile (exprNode_effect (exprData_getPairA (data)),
07773 exprNode_effect (exprData_getPairB (data)));
07774 break;
07775
07776 case XPR_BLOCK:
07777 ret = exprNode_makeBlock (exprNode_effect (exprData_getSingle (data)));
07778 break;
07779
07780 case XPR_STMT:
07781 ret = exprNode_statement (exprNode_effect (exprData_getSingle (data)));
07782 break;
07783
07784 case XPR_STMTLIST:
07785 ret = exprNode_concat (exprNode_effect (exprData_getPairA (data)),
07786 exprNode_effect (exprData_getPairB (data)));
07787 break;
07788
07789 case XPR_FTCASE:
07790 case XPR_CASE:
07791 ret = exprNode_caseMarker
07792 (exprNode_effect (exprData_getSingle (data)),
07793 TRUE);
07794 break;
07795
07796 case XPR_FTDEFAULT:
07797 case XPR_DEFAULT:
07798 ret = exprNode_createTok (exprData_getTok (data));
07799 break;
07800
07801 case XPR_SWITCH:
07802 ret = exprNode_switch (exprNode_effect (exprData_getPairA (data)),
07803 exprNode_effect (exprData_getPairB (data)));
07804 break;
07805
07806 case XPR_INIT:
07807 ret = exprNode_makeInitialization
07808 (exprData_getInitId (data),
07809 exprNode_effect (exprData_getInitNode (data)));
07810 break;
07811
07812 case XPR_FACCESS:
07813 ret = exprNode_fieldAccess (exprNode_effect (exprData_getFieldNode (data)),
07814 cstring_copy (exprData_getFieldName (data)));
07815 break;
07816
07817 case XPR_ARROW:
07818 ret = exprNode_arrowAccess (exprNode_effect (exprData_getFieldNode (data)),
07819 cstring_copy (exprData_getFieldName (data)));
07820 break;
07821
07822 case XPR_STRINGLITERAL:
07823 ret = e;
07824 break;
07825
07826 case XPR_NUMLIT:
07827 ret = e;
07828 break;
07829
07830 case XPR_NODE:
07831 ret = e;
07832 break;
07833
07834 }
07835
07836
07837
07838
07839 }
07840
07841 if (!innerEffect)
07842 {
07843 inEffect = FALSE;
07844 }
07845
07846 return ret;
07847 }
07848
07849 static cstring exprNode_rootVarName (exprNode e)
07850 {
07851 cstring ret;
07852 exprData data;
07853
07854 if (exprNode_isError (e))
07855 {
07856 return cstring_undefined;
07857 }
07858
07859 data = e->edata;
07860
07861 switch (e->kind)
07862 {
07863 case XPR_PARENS:
07864 ret = exprNode_rootVarName (exprData_getUopNode (data));
07865 break;
07866 case XPR_ASSIGN:
07867 ret = exprNode_rootVarName (exprData_getOpA (data));
07868 break;
07869 case XPR_CONST:
07870 case XPR_VAR:
07871 ret = exprData_getId (data);
07872 break;
07873 case XPR_LABEL:
07874 case XPR_TOK:
07875 case XPR_ITERCALL:
07876 case XPR_EMPTY:
07877 case XPR_CALL:
07878 case XPR_INITBLOCK:
07879 case XPR_BODY:
07880 case XPR_FETCH:
07881 case XPR_OP:
07882 case XPR_POSTOP:
07883 case XPR_PREOP:
07884 case XPR_OFFSETOF:
07885 case XPR_ALIGNOFT:
07886 case XPR_ALIGNOF:
07887 case XPR_SIZEOFT:
07888 case XPR_SIZEOF:
07889 case XPR_VAARG:
07890 case XPR_CAST:
07891 case XPR_ITER:
07892 case XPR_FOR:
07893 case XPR_FORPRED:
07894 case XPR_BREAK:
07895 case XPR_RETURN:
07896 case XPR_NULLRETURN:
07897 case XPR_COMMA:
07898 case XPR_COND:
07899 case XPR_IF:
07900 case XPR_IFELSE:
07901 case XPR_WHILE:
07902 case XPR_WHILEPRED:
07903 case XPR_DOWHILE:
07904 case XPR_GOTO:
07905 case XPR_CONTINUE:
07906 case XPR_FTDEFAULT:
07907 case XPR_DEFAULT:
07908 case XPR_SWITCH:
07909 case XPR_FTCASE:
07910 case XPR_CASE:
07911 case XPR_BLOCK:
07912 case XPR_STMT:
07913 case XPR_STMTLIST:
07914 case XPR_INIT:
07915 case XPR_FACCESS:
07916 case XPR_ARROW:
07917 case XPR_NODE:
07918 case XPR_NUMLIT:
07919 case XPR_STRINGLITERAL:
07920 ret = cstring_undefined;
07921 break;
07922 }
07923
07924 return ret;
07925 }
07926
07927 static cstring exprNode_doUnparse (exprNode e)
07928 {
07929 cstring ret;
07930 exprData data;
07931
07932 if (exprNode_isError (e))
07933 {
07934 static cstring error = cstring_undefined;
07935
07936 if (!cstring_isDefined (error))
07937 {
07938 error = cstring_makeLiteral ("<error>");
07939 }
07940
07941 return error;
07942 }
07943
07944 data = e->edata;
07945
07946 switch (e->kind)
07947 {
07948 case XPR_PARENS:
07949 ret = message ("(%s)", exprNode_unparse (exprData_getUopNode (e->edata)));
07950 break;
07951 case XPR_ASSIGN:
07952 ret = message ("%s %s %s",
07953 exprNode_unparse (exprData_getOpA (data)),
07954 lltok_unparse (exprData_getOpTok (data)),
07955 exprNode_unparse (exprData_getOpB (data)));
07956 break;
07957 case XPR_CALL:
07958 ret = message ("%s(%q)",
07959 exprNode_unparse (exprData_getFcn (data)),
07960 exprNodeList_unparse (exprData_getArgs (data)));
07961 break;
07962 case XPR_INITBLOCK:
07963 ret = message ("{ %q }", exprNodeList_unparse (exprData_getArgs (data)));
07964 break;
07965 case XPR_EMPTY:
07966 ret = cstring_undefined;
07967 break;
07968 case XPR_LABEL:
07969 ret = message ("%s:", exprData_getId (data));
07970 break;
07971 case XPR_CONST:
07972 case XPR_VAR:
07973 ret = cstring_copy (exprData_getId (data));
07974 break;
07975 case XPR_FETCH:
07976 ret = message ("%s[%s]", exprNode_unparse (exprData_getPairA (data)),
07977 exprNode_unparse (exprData_getPairB (data)));
07978 break;
07979 case XPR_BODY:
07980 ret = message ("<body>");
07981 break;
07982 case XPR_OP:
07983 ret = message ("%s %s %s",
07984 exprNode_unparse (exprData_getOpA (data)),
07985 lltok_unparse (exprData_getOpTok (data)),
07986 exprNode_unparse (exprData_getOpB (data)));
07987 break;
07988
07989 case XPR_PREOP:
07990 ret = message ("%s%s",
07991 lltok_unparse (exprData_getUopTok (data)),
07992 exprNode_unparse (exprData_getUopNode (data)));
07993 break;
07994
07995 case XPR_POSTOP:
07996 ret = message ("%s%s",
07997 exprNode_unparse (exprData_getUopNode (data)),
07998 lltok_unparse (exprData_getUopTok (data)));
07999 break;
08000
08001 case XPR_OFFSETOF:
08002 ret = message ("offsetof(%s,%q)",
08003 ctype_unparse (qtype_getType (exprData_getOffsetType (data))),
08004 cstringList_unparseSep (exprData_getOffsetName (data), cstring_makeLiteralTemp (".")));
08005 break;
08006
08007 case XPR_SIZEOFT:
08008 ret = message ("sizeof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
08009 break;
08010
08011 case XPR_SIZEOF:
08012 ret = message ("sizeof(%s)", exprNode_unparse (exprData_getSingle (data)));
08013 break;
08014
08015 case XPR_ALIGNOFT:
08016 ret = message ("alignof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
08017 break;
08018
08019 case XPR_ALIGNOF:
08020 ret = message ("alignof(%s)", exprNode_unparse (exprData_getSingle (data)));
08021 break;
08022
08023 case XPR_VAARG:
08024 ret = message ("va_arg(%s, %q)",
08025 exprNode_unparse (exprData_getCastNode (data)),
08026 qtype_unparse (exprData_getCastType (data)));
08027 break;
08028
08029 case XPR_ITERCALL:
08030 ret = message ("%q(%q)",
08031 uentry_getName (exprData_getIterCallIter (data)),
08032 exprNodeList_unparse (exprData_getIterCallArgs (data)));
08033 break;
08034 case XPR_ITER:
08035 ret = message ("%q(%q) %s %q",
08036 uentry_getName (exprData_getIterSname (data)),
08037 exprNodeList_unparse (exprData_getIterAlist (data)),
08038 exprNode_unparse (exprData_getIterBody (data)),
08039 uentry_getName (exprData_getIterEname (data)));
08040 break;
08041 case XPR_CAST:
08042 ret = message ("(%q)%s",
08043 qtype_unparse (exprData_getCastType (data)),
08044 exprNode_unparse (exprData_getCastNode (data)));
08045 break;
08046
08047 case XPR_FOR:
08048 ret = message ("%s %s",
08049 exprNode_unparse (exprData_getPairA (data)),
08050 exprNode_unparse (exprData_getPairB (data)));
08051 break;
08052
08053 case XPR_FORPRED:
08054 ret = message ("for (%s; %s; %s)",
08055 exprNode_unparse (exprData_getTripleInit (data)),
08056 exprNode_unparse (exprData_getTripleTest (data)),
08057 exprNode_unparse (exprData_getTripleInc (data)));
08058 break;
08059
08060 case XPR_GOTO:
08061 ret = message ("goto %s", exprData_getLiteral (data));
08062 break;
08063
08064 case XPR_CONTINUE:
08065 ret = cstring_makeLiteral ("continue");
08066 break;
08067
08068 case XPR_BREAK:
08069 ret = cstring_makeLiteral ("break");
08070 break;
08071
08072 case XPR_RETURN:
08073 ret = message ("return %s", exprNode_unparse (exprData_getSingle (data)));
08074 break;
08075
08076 case XPR_NULLRETURN:
08077 ret = cstring_makeLiteral ("return");
08078 break;
08079
08080 case XPR_COMMA:
08081 ret = message ("%s, %s",
08082 exprNode_unparse (exprData_getPairA (data)),
08083 exprNode_unparse (exprData_getPairB (data)));
08084 break;
08085
08086 case XPR_COND:
08087 ret = message ("%s ? %s : %s",
08088 exprNode_unparse (exprData_getTriplePred (data)),
08089 exprNode_unparse (exprData_getTripleTrue (data)),
08090 exprNode_unparse (exprData_getTripleFalse (data)));
08091 break;
08092 case XPR_IF:
08093 ret = message ("if (%s) %s",
08094 exprNode_unparse (exprData_getPairA (data)),
08095 exprNode_unparse (exprData_getPairB (data)));
08096 break;
08097
08098 case XPR_IFELSE:
08099 ret = message ("if (%s) %s else %s",
08100 exprNode_unparse (exprData_getTriplePred (data)),
08101 exprNode_unparse (exprData_getTripleTrue (data)),
08102 exprNode_unparse (exprData_getTripleFalse (data)));
08103 break;
08104 case XPR_WHILE:
08105 ret = message ("while (%s) %s",
08106 exprNode_unparse (exprData_getPairA (data)),
08107 exprNode_unparse (exprData_getPairB (data)));
08108 break;
08109
08110 case XPR_WHILEPRED:
08111 ret = cstring_copy (exprNode_unparse (exprData_getSingle (data)));
08112 break;
08113
08114 case XPR_TOK:
08115 ret = cstring_copy (lltok_unparse (exprData_getTok (data)));
08116 break;
08117
08118 case XPR_DOWHILE:
08119 ret = message ("do { %s } while (%s)",
08120 exprNode_unparse (exprData_getPairB (data)),
08121 exprNode_unparse (exprData_getPairA (data)));
08122 break;
08123
08124 case XPR_BLOCK:
08125 ret = message ("{ %s }", exprNode_unparseFirst (exprData_getSingle (data)));
08126 break;
08127
08128 case XPR_STMT:
08129 ret = cstring_copy (exprNode_unparse (exprData_getSingle (data)));
08130 break;
08131
08132 case XPR_STMTLIST:
08133 ret = message ("%s; %s",
08134 exprNode_unparse (exprData_getPairA (data)),
08135 exprNode_unparse (exprData_getPairB (data)));
08136 break;
08137
08138 case XPR_FTDEFAULT:
08139 case XPR_DEFAULT:
08140 ret = cstring_makeLiteral ("default:");
08141 break;
08142
08143 case XPR_SWITCH:
08144 ret = message ("switch (%s) %s",
08145 exprNode_unparse (exprData_getPairA (data)),
08146 exprNode_unparse (exprData_getPairB (data)));
08147 break;
08148
08149 case XPR_FTCASE:
08150 case XPR_CASE:
08151 ret = message ("case %s:",
08152 exprNode_unparse (exprData_getSingle (data)));
08153 break;
08154
08155 case XPR_INIT:
08156 ret = message ("%s = %s",
08157 idDecl_getName (exprData_getInitId (data)),
08158 exprNode_unparse (exprData_getInitNode (data)));
08159 break;
08160
08161 case XPR_FACCESS:
08162 ret = message ("%s.%s",
08163 exprNode_unparse (exprData_getFieldNode (data)),
08164 exprData_getFieldName (data));
08165 break;
08166
08167 case XPR_ARROW:
08168 ret = message ("%s->%s",
08169 exprNode_unparse (exprData_getFieldNode (data)),
08170 exprData_getFieldName (data));
08171 break;
08172
08173 case XPR_STRINGLITERAL:
08174 ret = cstring_copy (exprData_getLiteral (data));
08175 break;
08176
08177 case XPR_NUMLIT:
08178 ret = cstring_copy (exprData_getLiteral (data));
08179 break;
08180
08181 case XPR_NODE:
08182 ret = cstring_makeLiteral ("<node>");
08183 break;
08184 }
08185
08186 return ret;
08187 }
08188
08189 bool
08190 exprNode_isCharLit (exprNode e)
08191 {
08192 if (exprNode_isDefined (e))
08193 {
08194 return (multiVal_isChar (exprNode_getValue (e)));
08195 }
08196 else
08197 {
08198 return FALSE;
08199 }
08200 }
08201
08202 bool
08203 exprNode_isNumLit (exprNode e)
08204 {
08205 if (exprNode_isDefined (e))
08206 {
08207 return (multiVal_isInt (exprNode_getValue (e)));
08208 }
08209 else
08210 {
08211 return FALSE;
08212 }
08213 }
08214
08215 static bool
08216 exprNode_isFalseConstant (exprNode e)
08217 {
08218 if (exprNode_isDefined (e))
08219 {
08220 cstring s = exprNode_rootVarName (e);
08221
08222 if (cstring_equal (s, context_getFalseName ()))
08223 {
08224 return TRUE;
08225 }
08226 }
08227
08228 return FALSE;
08229 }
08230
08231 bool
08232 exprNode_matchLiteral (ctype expected, exprNode e)
08233 {
08234 if (exprNode_isDefined (e))
08235 {
08236 multiVal m = exprNode_getValue (e);
08237
08238 if (multiVal_isDefined (m))
08239 {
08240 if (multiVal_isInt (m))
08241 {
08242 long int val = multiVal_forceInt (m);
08243
08244 if (ctype_isDirectBool (ctype_realishType (expected)))
08245 {
08246 if (val == 0)
08247 {
08248 return FALSE;
08249 }
08250 else
08251 {
08252 return FALSE;
08253 }
08254 }
08255
08256 if (ctype_isRealInt (expected))
08257 {
08258
08259
08260
08261
08262 if (ctype_isUnsigned (expected))
08263 {
08264 if (val < 0)
08265 {
08266 return FALSE;
08267 }
08268 }
08269
08270
08271
08272
08273
08274
08275 DPRINTF (("Here: %s => %s", exprNode_unparse (e), ctype_unparse (expected)));
08276 DPRINTF (("Type: %s / %s", ctype_unparse (exprNode_getType (e)),
08277 bool_unparse (ctype_isInt (exprNode_getType (e)))));
08278
08279 if (context_getFlag (FLG_NUMLITERAL)
08280 && (ctype_isRegularInt (exprNode_getType (e)) || val == 0)) {
08281 return TRUE;
08282 } else {
08283 if (val == 0) {
08284 return TRUE;
08285 } else {
08286 return FALSE;
08287 }
08288 }
08289 }
08290 else if (ctype_isChar (expected))
08291 {
08292 return FALSE;
08293 }
08294 else if (ctype_isArrayPtr (expected))
08295 {
08296 return (val == 0);
08297 }
08298 else if (ctype_isAnyFloat (expected))
08299 {
08300 return (context_getFlag (FLG_NUMLITERAL));
08301 }
08302 else
08303 {
08304 return FALSE;
08305 }
08306 }
08307 else if (multiVal_isDouble (m))
08308 {
08309 if (ctype_isAnyFloat (expected))
08310 {
08311 return TRUE;
08312 }
08313 }
08314 else if (multiVal_isChar (m))
08315 {
08316 char val = multiVal_forceChar (m);
08317
08318 if (ctype_isChar (expected))
08319 {
08320 if (ctype_isUnsigned (expected) && ((int)val) < 0)
08321 {
08322 return FALSE;
08323 }
08324 else
08325 {
08326 return TRUE;
08327 }
08328 }
08329 }
08330 else
08331 {
08332 return FALSE;
08333 }
08334 }
08335 }
08336
08337 return FALSE;
08338 }
08339
08340 bool
08341 exprNode_matchType (ctype expected, exprNode e)
08342 {
08343 ctype actual;
08344
08345 if (!exprNode_isDefined (e)) return TRUE;
08346
08347 actual = ctype_realishType (exprNode_getType (e));
08348
08349 if (ctype_match (ctype_realishType (expected), actual))
08350 {
08351 return TRUE;
08352 }
08353
08354 llassert (!exprNode_isError (e));
08355 return (exprNode_matchLiteral (expected, e));
08356 }
08357
08358 static bool
08359 exprNode_matchTypes (exprNode e1, exprNode e2)
08360 {
08361 ctype t1;
08362 ctype t2;
08363
08364 if (!exprNode_isDefined (e1)) return TRUE;
08365 if (!exprNode_isDefined (e2)) return TRUE;
08366
08367
08368
08369
08370
08371 t1 = ctype_realishType (exprNode_getType (e1));
08372 t2 = ctype_realishType (exprNode_getType (e2));
08373
08374 if (ctype_match (t1, t2))
08375 {
08376 return TRUE;
08377 }
08378
08379 return (exprNode_matchLiteral (t1, e2) || exprNode_matchLiteral (t2, e1));
08380 }
08381
08382
08383
08384
08385
08386 static bool
08387 exprNode_matchArgType (ctype ct, exprNode e)
08388 {
08389 ctype et;
08390
08391 if (!exprNode_isDefined (e))
08392 {
08393 return TRUE;
08394 }
08395
08396 et = ctype_realType (exprNode_getType (e));
08397
08398 if (ctype_matchArg (ct, et)) return TRUE;
08399
08400 llassert (!exprNode_isError (e));
08401 return (exprNode_matchLiteral (ct, e));
08402 }
08403
08404 static exprNodeSList
08405 exprNode_flatten ( exprNode e)
08406 {
08407 if (exprNode_isDefined (e))
08408 {
08409 if (e->kind == XPR_STMTLIST)
08410 {
08411 return (exprNodeSList_append
08412 (exprNode_flatten (exprData_getPairA (e->edata)),
08413 exprNode_flatten (exprData_getPairB (e->edata))));
08414 }
08415 else if (e->kind == XPR_BLOCK)
08416 {
08417 return (exprNode_flatten (exprData_getSingle (e->edata)));
08418 }
08419 else
08420 {
08421 return (exprNodeSList_singleton (e));
08422 }
08423 }
08424
08425 return exprNodeSList_new ();
08426 }
08427
08428 static exprNode
08429 exprNode_lastStatement ( exprNode e)
08430 {
08431 if (exprNode_isDefined (e))
08432 {
08433 if (e->kind == XPR_STMTLIST)
08434 {
08435 exprNode b = exprData_getPairB (e->edata);
08436
08437 if (exprNode_isDefined (b))
08438 {
08439 return exprNode_lastStatement (b);
08440 }
08441 else
08442 {
08443 return exprNode_lastStatement (exprData_getPairA (e->edata));
08444 }
08445 }
08446 else if (e->kind == XPR_BLOCK)
08447 {
08448 return (exprNode_lastStatement (exprData_getSingle (e->edata)));
08449 }
08450 else
08451 {
08452 return (e);
08453 }
08454 }
08455
08456 return exprNode_undefined;
08457 }
08458
08459 static exprNode
08460 exprNode_firstStatement ( exprNode e)
08461 {
08462 if (exprNode_isDefined (e))
08463 {
08464 if (e->kind == XPR_STMTLIST)
08465 {
08466 exprNode b = exprData_getPairA (e->edata);
08467
08468 if (exprNode_isDefined (b))
08469 {
08470 return exprNode_firstStatement (b);
08471 }
08472 else
08473 {
08474 return exprNode_firstStatement (exprData_getPairB (e->edata));
08475 }
08476 }
08477 else if (e->kind == XPR_BLOCK)
08478 {
08479 return (exprNode_firstStatement (exprData_getSingle (e->edata)));
08480 }
08481 else
08482 {
08483 return (e);
08484 }
08485 }
08486
08487 return exprNode_undefined;
08488 }
08489
08490 static void
08491 exprNode_mergeUSs (exprNode res, exprNode other)
08492 {
08493 if (exprNode_isDefined (res) && exprNode_isDefined (other))
08494 {
08495 res->msets = sRefSet_union (res->msets, other->msets);
08496 res->sets = sRefSet_union (res->sets, other->sets);
08497 res->uses = sRefSet_union (res->uses, other->uses);
08498 }
08499 }
08500
08501 static void
08502 exprNode_mergeCondUSs (exprNode res, exprNode other1, exprNode other2)
08503 {
08504 if (exprNode_isDefined (res))
08505 {
08506 if (exprNode_isDefined (other1))
08507 {
08508 res->sets = sRefSet_union (res->sets, other1->sets);
08509 res->msets = sRefSet_union (res->msets, other1->msets);
08510 res->uses = sRefSet_union (res->uses, other1->uses);
08511 }
08512 if (exprNode_isDefined (other2))
08513 {
08514 res->sets = sRefSet_union (res->sets, other2->sets);
08515 res->msets = sRefSet_union (res->msets, other2->msets);
08516 res->uses = sRefSet_union (res->uses, other2->uses);
08517 }
08518 }
08519 }
08520
08521
08522
08523
08524
08525
08526
08527 static void
08528 exprNode_addUse (exprNode e, sRef s)
08529 {
08530 if (exprNode_isDefined (e))
08531 {
08532 e->uses = sRefSet_insert (e->uses, s);
08533 }
08534 }
08535
08536 void
08537 exprNode_checkUse (exprNode e, sRef s, fileloc loc)
08538 {
08539 if (sRef_isKnown (s) && !sRef_isConst (s))
08540 {
08541
08542
08543
08544
08545 DPRINTF (("Check use: %s / %s",
08546 exprNode_unparse (e), sRef_unparse (s)));
08547
08548 exprNode_addUse (e, s);
08549
08550 if (!context_inProtectVars ())
08551 {
08552
08553
08554
08555
08556 sRef errorRef = sRef_undefined;
08557 sRef lastRef = sRef_undefined;
08558 bool deadRef = FALSE;
08559 bool unuseable = FALSE;
08560 bool errorMaybe = FALSE;
08561
08562 while (sRef_isValid (s) && sRef_isKnown (s))
08563 {
08564 ynm readable = sRef_isReadable (s);
08565
08566 if (!(ynm_toBoolStrict (readable)))
08567 {
08568 if (ynm_isMaybe (readable))
08569 {
08570 lastRef = errorRef;
08571 errorRef = s;
08572 deadRef = sRef_isPossiblyDead (errorRef);
08573 unuseable = sRef_isUnuseable (errorRef);
08574 errorMaybe = TRUE;
08575 }
08576 else
08577 {
08578 lastRef = errorRef;
08579 errorRef = s;
08580 deadRef = sRef_isDead (errorRef);
08581 unuseable = sRef_isUnuseable (errorRef);
08582 errorMaybe = FALSE;
08583 }
08584
08585 if (!sRef_isPartial (s))
08586 {
08587 sRef_setDefined (s, fileloc_undefined);
08588 }
08589 }
08590
08591 s = sRef_getBaseSafe (s);
08592 }
08593
08594 if (sRef_isValid (errorRef))
08595 {
08596 if (sRef_isValid (lastRef) && sRef_isField (lastRef)
08597 && sRef_isPointer (errorRef))
08598 {
08599 errorRef = lastRef;
08600 }
08601
08602 if (deadRef)
08603 {
08604 if (sRef_isThroughArrayFetch (errorRef))
08605 {
08606 if (optgenerror
08607 (FLG_STRICTUSERELEASED,
08608 message ("%q %q may be used after being released",
08609 sRef_unparseKindNamePlain (errorRef),
08610 sRef_unparse (errorRef)),
08611 loc))
08612 {
08613 sRef_showRefKilled (errorRef);
08614
08615 if (sRef_isKept (errorRef))
08616 {
08617 sRef_clearAliasState (errorRef, loc);
08618 }
08619 }
08620 }
08621 else
08622 {
08623 DPRINTF (("HERE: %s", sRef_unparse (errorRef)));
08624
08625 if (optgenerror
08626 (FLG_USERELEASED,
08627 message ("%q %q %qused after being released",
08628 sRef_unparseKindNamePlain (errorRef),
08629 sRef_unparse (errorRef),
08630 cstring_makeLiteral (errorMaybe
08631 ? "may be " : "")),
08632 loc))
08633 {
08634 sRef_showRefKilled (errorRef);
08635
08636 if (sRef_isKept (errorRef))
08637 {
08638 sRef_clearAliasState (errorRef, loc);
08639 }
08640 }
08641 }
08642 }
08643 else if (unuseable)
08644 {
08645 if (optgenerror
08646 (FLG_USEDEF,
08647 message ("%q %q%qused in inconsistent state",
08648 sRef_unparseKindName (errorRef),
08649 sRef_unparseOpt (errorRef),
08650 cstring_makeLiteral (errorMaybe ? "may be " : "")),
08651 loc))
08652 {
08653 sRef_showStateInconsistent (errorRef);
08654 }
08655 }
08656 else
08657 {
08658 DPRINTF (("HERE: %s", sRef_unparse (errorRef)));
08659
08660 voptgenerror
08661 (FLG_USEDEF,
08662 message ("%q %q%qused before definition",
08663 sRef_unparseKindName (errorRef),
08664 sRef_unparseOpt (errorRef),
08665 cstring_makeLiteral (errorMaybe ? "may be " : "")),
08666 loc);
08667 }
08668
08669 sRef_setDefined (errorRef, loc);
08670
08671 if (sRef_isAddress (errorRef))
08672 {
08673 sRef_setDefined (sRef_getRootBase (errorRef), loc);
08674 }
08675 }
08676 }
08677 }
08678
08679 setCodePoint ();
08680 }
08681
08682 static void
08683 checkSafeUse (exprNode e, sRef s)
08684 {
08685 if (exprNode_isDefined (e) && sRef_isKnown (s))
08686 {
08687 e->uses = sRefSet_insert (e->uses, s);
08688 }
08689 }
08690
08691 static void
08692 exprNode_checkSetAny (exprNode e, cstring name)
08693 {
08694 if (exprNode_isDefined (e))
08695 {
08696 e->sets = sRefSet_insert (e->sets, sRef_makeUnconstrained (name));
08697 }
08698 }
08699
08700 void
08701 exprNode_checkSet (exprNode e, sRef s)
08702 {
08703 sRef defines = sRef_undefined;
08704
08705 if (sRef_isValid (s) && !sRef_isNothing (s))
08706 {
08707 uentry ue = sRef_getBaseUentry (s);
08708
08709 if (uentry_isValid (ue))
08710 {
08711 uentry_setLset (ue);
08712 }
08713
08714 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
08715 {
08716 voptgenerror (FLG_USEDEF,
08717 message ("Attempt to set unuseable storage: %q",
08718 sRef_unparse (s)),
08719 exprNode_loc (e));
08720 }
08721
08722 if (sRef_isMeaningful (s))
08723 {
08724
08725 if (sRef_isDead (s))
08726 {
08727 sRef base = sRef_getBaseSafe (s);
08728
08729 if (sRef_isValid (base)
08730 && sRef_isDead (base))
08731 {
08732 sRef_setPartial (s, exprNode_loc (e));
08733 }
08734
08735 defines = s;
08736 }
08737 else if (sRef_isPartial (s))
08738 {
08739 sRef eref = exprNode_getSref (e);
08740
08741 if (!sRef_isPartial (eref))
08742 {
08743
08744
08745
08746
08747 sRef_setDefinedComplete (eref, exprNode_loc (e));
08748 }
08749 else
08750 {
08751 sRef_setPartialDefinedComplete (eref, exprNode_loc (e));
08752 }
08753
08754 if (sRef_isMeaningful (eref))
08755 {
08756 defines = eref;
08757 }
08758 else
08759 {
08760 defines = s;
08761 }
08762 }
08763 else if (sRef_isAllocated (s))
08764 {
08765 sRef eref = exprNode_getSref (e);
08766
08767
08768 if (!sRef_isAllocated (eref))
08769 {
08770 sRef_setDefinedComplete (eref, exprNode_loc (e));
08771 }
08772 else
08773 {
08774 sRef base = sRef_getBaseSafe (eref);
08775
08776 if (sRef_isValid (base))
08777 {
08778 sRef_setPdefined (base, exprNode_loc (e));
08779 }
08780 }
08781
08782 defines = s;
08783 }
08784 else
08785 {
08786 sRef_setDefinedNCComplete (s, exprNode_loc (e));
08787 defines = s;
08788 }
08789
08790 }
08791 else
08792 {
08793 defines = s;
08794 }
08795 }
08796
08797 if (exprNode_isDefined (e) && sRef_isValid (defines))
08798 {
08799 e->sets = sRefSet_insert (e->sets, defines);
08800 }
08801 }
08802
08803 void
08804 exprNode_checkMSet (exprNode e, sRef s)
08805 {
08806 if (sRef_isValid (s) && !sRef_isNothing (s))
08807 {
08808 uentry ue = sRef_getBaseUentry (s);
08809
08810 if (uentry_isValid (ue))
08811 {
08812 uentry_setLset (ue);
08813 }
08814
08815 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
08816 {
08817 voptgenerror (FLG_USEDEF,
08818 message ("Attempt to set unuseable storage: %q", sRef_unparse (s)),
08819 exprNode_loc (e));
08820 }
08821
08822 if (sRef_isMeaningful (s))
08823 {
08824 sRef_setDefinedComplete (s, exprNode_loc (e));
08825 }
08826
08827 if (exprNode_isDefined (e))
08828 {
08829 e->msets = sRefSet_insert (e->msets, s);
08830 }
08831 }
08832 }
08833
08834 static void
08835 checkUnspecCall ( exprNode fcn, uentryList params, exprNodeList args)
08836 {
08837 checkAnyCall (fcn, cstring_undefined, params, args,
08838 FALSE, sRefSet_undefined, FALSE, 0);
08839 }
08840
08841 static void
08842 checkOneArg (uentry ucurrent, exprNode current,
08843 exprNode fcn, bool isSpec, int argno, int totargs)
08844 {
08845 setCodePoint ();
08846
08847 if (uentry_isYield (ucurrent))
08848 {
08849 sRef_setDefined (exprNode_getSref (current), exprNode_loc (current));
08850 exprNode_checkSet (current, current->sref);
08851 }
08852 else
08853 {
08854 if (uentry_isSefParam (ucurrent))
08855 {
08856 sRefSet sets = current->sets;
08857 sRef ref = exprNode_getSref (current);
08858
08859 if (sRef_isMacroParamRef (ref))
08860 {
08861 uentry ue = sRef_getUentry (ref);
08862
08863 if (!uentry_isSefParam (ue))
08864 {
08865 voptgenerror
08866 (FLG_SEFPARAMS,
08867 message
08868 ("Parameter %d to %s is declared sef, but "
08869 "the argument is a macro parameter declared "
08870 "without sef: %s",
08871 argno, exprNode_unparse (fcn),
08872 exprNode_unparse (current)),
08873 exprNode_loc (current));
08874 }
08875 }
08876
08877 if (!sRefSet_isEmpty (sets))
08878 {
08879 sRefSet reported = sRefSet_undefined;
08880
08881 sRefSet_realElements (current->sets, el)
08882 {
08883 if (sRefSet_isSameNameMember (reported, el))
08884 {
08885 ;
08886 }
08887 else
08888 {
08889 if (sRef_isUnconstrained (el))
08890 {
08891 voptgenerror
08892 (FLG_SEFUNSPEC,
08893 message
08894 ("Parameter %d to %s is declared sef, but "
08895 "the argument calls unconstrained function %s "
08896 "(no guarantee it will not modify something): %s",
08897 argno, exprNode_unparse (fcn),
08898 sRef_unconstrainedName (el),
08899 exprNode_unparse (current)),
08900 exprNode_loc (current));
08901 }
08902 else
08903 {
08904 voptgenerror
08905 (FLG_SEFPARAMS,
08906 message
08907 ("Parameter %d to %s is declared sef, but "
08908 "the argument may modify %q: %s",
08909 argno, exprNode_unparse (fcn),
08910 sRef_unparse (el),
08911 exprNode_unparse (current)),
08912 exprNode_loc (current));
08913 }
08914 }
08915 } end_sRefSet_realElements;
08916 }
08917 }
08918
08919 checkPassTransfer (current, ucurrent, isSpec, fcn, argno, totargs);
08920 exprNode_mergeUSs (fcn, current);
08921 }
08922 }
08923
08924 static void
08925 checkAnyCall ( exprNode fcn,
08926 cstring fname,
08927 uentryList pn,
08928 exprNodeList args,
08929 bool hasMods, sRefSet mods,
08930 bool isSpec,
08931 int specialArgs)
08932 {
08933 int paramno = 0;
08934 int nargs = exprNodeList_size (args);
08935
08936 setCodePoint ();
08937
08938
08939
08940
08941
08942
08943 uentryList_reset (pn);
08944
08945
08946
08947
08948
08949
08950
08951 exprNodeList_elements (args, current)
08952 {
08953 paramno++;
08954
08955 if (exprNode_isDefined (current))
08956 {
08957 if ((!uentryList_isUndefined (pn) && !uentryList_isFinished (pn)))
08958 {
08959 uentry ucurrent = uentryList_current (pn);
08960
08961 if (specialArgs == 0
08962 || (paramno < specialArgs))
08963 {
08964 checkOneArg (ucurrent, current, fcn, isSpec, paramno, nargs);
08965
08966 if (context_maybeSet (FLG_ALIASUNIQUE))
08967 {
08968 if (uentry_isOnly (ucurrent)
08969 || uentry_isUnique (ucurrent))
08970 {
08971 checkUniqueParams (fcn, current, args,
08972 paramno, ucurrent);
08973 }
08974 }
08975 }
08976 }
08977 else
08978 {
08979 if (specialArgs == 0)
08980 {
08981 exprNode_checkUseParam (current);
08982 }
08983
08984 exprNode_mergeUSs (fcn, current);
08985 }
08986 }
08987 uentryList_advanceSafe (pn);
08988 } end_exprNodeList_elements;
08989
08990 if (hasMods)
08991 {
08992 setCodePoint ();
08993
08994 sRefSet_allElements (mods, s)
08995 {
08996 sRef fb;
08997 sRef rb = sRef_getRootBase (s);
08998
08999 if (sRef_isGlobal (rb))
09000 {
09001 context_usedGlobal (rb);
09002 }
09003
09004 fb = sRef_fixBaseParam (s, args);
09005
09006 if (!sRef_isMacroParamRef (fb))
09007 {
09008 if (sRef_isNothing (fb))
09009 {
09010 ;
09011 }
09012 else
09013 {
09014 if (sRef_isValid (fb))
09015 {
09016 uentry ue = sRef_getBaseUentry (s);
09017
09018 if (uentry_isValid (ue))
09019 {
09020 uentry_setLset (ue);
09021 }
09022 }
09023
09024 fcn->sets = sRefSet_insert (fcn->sets, fb);
09025 }
09026 }
09027 sRef_clearDerivedComplete (s);
09028 } end_sRefSet_allElements;
09029
09030 setCodePoint ();
09031 }
09032 else
09033 {
09034 if (context_hasMods ())
09035 {
09036 if (context_maybeSet (FLG_MODUNCON))
09037 {
09038 voptgenerror
09039 (FLG_MODUNCON,
09040 message ("Undetected modification possible "
09041 "from call to unconstrained function %s: %s",
09042 fname,
09043 exprNode_unparse (fcn)),
09044 exprNode_loc (fcn));
09045 }
09046 }
09047 else
09048 {
09049 if (context_maybeSet (FLG_MODUNCONNOMODS)
09050 && !(context_inIterDef () || context_inIterEnd ()))
09051 {
09052 voptgenerror
09053 (FLG_MODUNCONNOMODS,
09054 message ("Undetected modification possible "
09055 "from call to unconstrained function %s: %s",
09056 fname,
09057 exprNode_unparse (fcn)),
09058 exprNode_loc (fcn));
09059 }
09060 }
09061
09062 exprNode_checkSetAny (fcn, fname);
09063 }
09064 }
09065
09066 void exprNode_checkUseParam (exprNode current)
09067 {
09068 if (exprNode_isDefined (current))
09069 {
09070 exprNode_checkUse (current, current->sref, current->loc);
09071 }
09072 }
09073
09074 static ctype
09075 checkNumerics (ctype tr1, ctype tr2, ctype te1, ctype te2,
09076 exprNode e1, exprNode e2,
09077 lltok op)
09078 {
09079 ctype ret = tr1;
09080
09081 if (!ctype_match (tr1, tr2))
09082 {
09083 if ((ctype_isRealInt (tr1) || ctype_isReal (tr1)) &&
09084 (ctype_isRealInt (tr2) || ctype_isReal (tr2)))
09085 {
09086 ;
09087 }
09088 else
09089 {
09090 (void) gentypeerror
09091 (tr1, e1, tr2, e2,
09092 message ("Incompatible types for %s (%s, %s): %s %s %s",
09093 lltok_unparse (op),
09094 ctype_unparse (te1),
09095 ctype_unparse (te2),
09096 exprNode_unparse (e1), lltok_unparse (op),
09097 exprNode_unparse (e2)),
09098 e1->loc);
09099 }
09100 ret = ctype_unknown;
09101 }
09102 else
09103 {
09104 if (ctype_isForceRealNumeric (&tr1) && ctype_isForceRealNumeric (&tr2))
09105 {
09106 ret = ctype_resolveNumerics (tr1, tr2);
09107 }
09108 else if (!context_msgStrictOps ())
09109 {
09110 if (ctype_isPointer (tr1))
09111 {
09112 if (ctype_isPointer (tr2) && !exprNode_isNullValue (e2))
09113 {
09114 ret = ctype_int;
09115 }
09116 else if (ctype_isInt (tr2))
09117 {
09118 ret = te1;
09119 }
09120 else
09121 {
09122 ret = ctype_unknown;
09123 }
09124 }
09125 else if (ctype_isPointer (tr2))
09126 {
09127 if (ctype_isPointer (tr1))
09128 {
09129 ret = ctype_int;
09130 }
09131 else if (ctype_isInt (tr1))
09132 {
09133 ret = te2;
09134 }
09135 else
09136 {
09137 ret = ctype_unknown;
09138 }
09139 }
09140 else
09141 {
09142 ret = ctype_resolveNumerics (tr1, tr2);
09143 }
09144 }
09145 else
09146 {
09147 int opid = lltok_getTok (op);
09148 bool comparop = (opid == EQ_OP || opid == NE_OP
09149 || opid == TLT || opid == TGT
09150 || opid == LE_OP || opid == GE_OP);
09151
09152 if (!ctype_isNumeric (tr1) && !ctype_isNumeric (tr2))
09153 {
09154 if (comparop
09155 && ((ctype_isEnum (tr1) && ctype_isEnum (tr2))
09156 || (ctype_isBool (tr1) && ctype_isBool (tr2))
09157 || (ctype_isChar (tr1) && ctype_isChar (tr2))))
09158 {
09159 ;
09160 }
09161 else
09162 {
09163 if (ctype_sameName (te1, te2))
09164 {
09165 voptgenerror
09166 (FLG_STRICTOPS,
09167 message ("Operands of %s are non-numeric (%t): %s %s %s",
09168 lltok_unparse (op), te1,
09169 exprNode_unparse (e1), lltok_unparse (op),
09170 exprNode_unparse (e2)),
09171 e1->loc);
09172 }
09173 else
09174 {
09175 voptgenerror
09176 (FLG_STRICTOPS,
09177 message ("Operands of %s are non-numerics (%t, %t): %s %s %s",
09178 lltok_unparse (op), te1, te2,
09179 exprNode_unparse (e1), lltok_unparse (op),
09180 exprNode_unparse (e2)),
09181 e1->loc);
09182 }
09183 }
09184 }
09185 else if (!ctype_isNumeric (tr1))
09186 {
09187 voptgenerror
09188 (FLG_STRICTOPS,
09189 message ("Right operand of %s is non-numeric (%t): %s %s %s",
09190 lltok_unparse (op), te1,
09191 exprNode_unparse (e1), lltok_unparse (op),
09192 exprNode_unparse (e2)),
09193 e1->loc);
09194 }
09195 else
09196 {
09197 if (!ctype_isNumeric (tr2))
09198 {
09199 voptgenerror
09200 (FLG_STRICTOPS,
09201 message ("Left operand of %s is non-numeric (%t): %s %s %s",
09202 lltok_unparse (op), te2,
09203 exprNode_unparse (e1), lltok_unparse (op),
09204 exprNode_unparse (e2)),
09205 e2->loc);
09206 }
09207 }
09208
09209 ret = ctype_unknown;
09210 }
09211 }
09212
09213 return ret;
09214 }
09215
09216 static void
09217 abstractOpError (ctype tr1, ctype tr2, lltok op,
09218 exprNode e1, exprNode e2,
09219 fileloc loc1, fileloc loc2)
09220 {
09221 if (ctype_isRealAbstract (tr1) && ctype_isRealAbstract (tr2))
09222 {
09223 if (ctype_match (tr1, tr2))
09224 {
09225 voptgenerror
09226 (FLG_ABSTRACT,
09227 message ("Operands of %s are abstract type (%t): %s %s %s",
09228 lltok_unparse (op), tr1,
09229 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
09230 loc1);
09231 }
09232 else
09233 {
09234 voptgenerror
09235 (FLG_ABSTRACT,
09236 message ("Operands of %s are abstract types (%t, %t): %s %s %s",
09237 lltok_unparse (op), tr1, tr2,
09238 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
09239 loc1);
09240 }
09241 }
09242 else if (ctype_isRealAbstract (tr1))
09243 {
09244 voptgenerror
09245 (FLG_ABSTRACT,
09246 message ("Left operand of %s is abstract type (%t): %s %s %s",
09247 lltok_unparse (op), tr1,
09248 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
09249 loc1);
09250 }
09251 else
09252 {
09253 if (ctype_isRealAbstract (tr2))
09254 {
09255 voptgenerror
09256 (FLG_ABSTRACT,
09257 message ("Right operand of %s is abstract type (%t): %s %s %s",
09258 lltok_unparse (op), tr2,
09259 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
09260 loc2);
09261 }
09262 }
09263 }
09264
09265
09266
09267
09268
09269
09270
09271
09272
09273
09274
09275
09276
09277
09278
09279
09280
09281
09282
09283
09284
09285
09286
09287 static void
09288 checkOneRepExpose (sRef ysr, sRef base,
09289 exprNode e1,
09290 exprNode e2, ctype ct,
09291 sRef s2b)
09292 {
09293 if (!(sRef_isOnly (ysr) || sRef_isKeep (ysr)
09294 || sRef_isOwned (ysr) || sRef_isExposed (ysr)))
09295 {
09296 if (sRef_isAnyParam (base) && !sRef_isExposed (base))
09297 {
09298 if (sRef_isIReference (ysr))
09299 {
09300 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
09301 {
09302 voptgenerror
09303 (FLG_ASSIGNEXPOSE,
09304 message
09305 ("Assignment of mutable component of parameter %q "
09306 "to component of abstract "
09307 "type %s exposes rep: %s = %s",
09308 sRef_unparse (base),
09309 ctype_unparse (ct),
09310 exprNode_unparse (e1), exprNode_unparse (e2)),
09311 e1->loc);
09312 }
09313 else
09314 {
09315 voptgenerror
09316 (FLG_ASSIGNEXPOSE,
09317 message
09318 ("Assignment of mutable component of parameter %q "
09319 "(through alias %q) to component of abstract "
09320 "type %s exposes rep: %s = %s",
09321 sRef_unparse (base),
09322 sRef_unparse (e2->sref),
09323 ctype_unparse (ct),
09324 exprNode_unparse (e1), exprNode_unparse (e2)),
09325 e1->loc);
09326 }
09327 }
09328 else
09329 {
09330 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
09331 {
09332 voptgenerror
09333 (FLG_ASSIGNEXPOSE,
09334 message ("Assignment of mutable parameter %q "
09335 "to component of abstract type %s "
09336 "exposes rep: %s = %s",
09337 sRef_unparse (base),
09338 ctype_unparse (ct),
09339 exprNode_unparse (e1),
09340 exprNode_unparse (e2)),
09341 e1->loc);
09342 }
09343 else
09344 {
09345 voptgenerror
09346 (FLG_ASSIGNEXPOSE,
09347 message ("Assignment of mutable parameter %q "
09348 "(through alias %q) to "
09349 "component of abstract type %s exposes "
09350 "rep: %s = %s",
09351 sRef_unparse (base),
09352 sRef_unparse (e2->sref),
09353 ctype_unparse (ct),
09354 exprNode_unparse (e1),
09355 exprNode_unparse (e2)),
09356 e1->loc);
09357 }
09358 }
09359 }
09360
09361 if (sRef_isGlobal (s2b))
09362 {
09363 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
09364 {
09365 voptgenerror
09366 (FLG_REPEXPOSE,
09367 message ("Assignment of global %q "
09368 "to component of "
09369 "abstract type %s exposes rep: %s = %s",
09370 sRef_unparse (base),
09371 ctype_unparse (ct),
09372 exprNode_unparse (e1), exprNode_unparse (e2)),
09373 e1->loc);
09374 }
09375 else
09376 {
09377 voptgenerror
09378 (FLG_REPEXPOSE,
09379 message ("Assignment of global %q (through alias %q) "
09380 "to component of "
09381 "abstract type %s exposes rep: %s = %s",
09382 sRef_unparse (base),
09383 sRef_unparse (e2->sref),
09384 ctype_unparse (ct),
09385 exprNode_unparse (e1), exprNode_unparse (e2)),
09386 e1->loc);
09387 }
09388 }
09389 }
09390 }
09391
09392 static void
09393 doAssign ( exprNode e1, exprNode e2, bool isInit)
09394 {
09395 if (ctype_isRealFunction (exprNode_getType (e1))
09396 && !ctype_isRealPointer (exprNode_getType (e1)))
09397 {
09398 voptgenerror
09399 (FLG_TYPE,
09400 message ("Invalid left-hand side of assignment (function type %s): %s",
09401 ctype_unparse (exprNode_getType (e1)),
09402 exprNode_unparse (e1)),
09403 e1->loc);
09404 }
09405
09406 if (context_getFlag (FLG_ASSIGNEXPOSE) && ctype_isMutable (e2->typ))
09407 {
09408 ctype t2 = exprNode_getType (e2);
09409 sRef sr = sRef_getRootBase (e1->sref);
09410 ctype ct = sRef_getType (sr);
09411
09412 if (ctype_isAbstract (t2)
09413 && !(uentry_isMutableDatatype (usymtab_getTypeEntry (ctype_typeId (t2)))))
09414 {
09415
09416 goto donerepexpose;
09417 }
09418
09419 if (ctype_isAbstract (ct) && sRef_isIReference (e1->sref))
09420 {
09421 sRef s2b = sRef_getRootBase (e2->sref);
09422 sRef s1 = e1->sref;
09423 sRef s1b = sRef_getRootBase (s1);
09424 sRefSet aliases;
09425
09426 aliases = usymtab_canAlias (e2->sref);
09427
09428 if (!sRef_similar (s2b, s1b)
09429 && !sRef_isExposed (s1)
09430 && !(sRef_isOnly (s2b) || sRef_isKeep (s2b) || sRef_isExposed (s2b)))
09431 {
09432 if (sRef_isAnyParam (s2b) && !sRef_isOnly (s2b)
09433 && !sRef_isOwned (s2b) && !sRef_isKeep (s2b)
09434 && !sRef_isExposed (s2b))
09435 {
09436 if (sRef_isIReference (e2->sref))
09437 {
09438 voptgenerror
09439 (FLG_ASSIGNEXPOSE,
09440 message
09441 ("Assignment of mutable component of parameter %q "
09442 "to component of abstract type %s exposes rep: %s = %s",
09443 sRef_unparse (s2b),
09444 ctype_unparse (ct),
09445 exprNode_unparse (e1), exprNode_unparse (e2)),
09446 e1->loc);
09447 }
09448 else
09449 {
09450 voptgenerror
09451 (FLG_ASSIGNEXPOSE,
09452 message ("Assignment of mutable parameter %q to "
09453 "component of abstract type %s exposes rep: %s = %s",
09454 sRef_unparse (s2b),
09455 ctype_unparse (ct),
09456 exprNode_unparse (e1), exprNode_unparse (e2)),
09457 e1->loc);
09458 }
09459 }
09460
09461 if (sRef_isGlobal (s2b))
09462 {
09463 voptgenerror
09464 (FLG_ASSIGNEXPOSE,
09465 message ("Assignment of global %q to component of "
09466 "abstract type %s exposes rep: %s = %s",
09467 sRef_unparse (s2b),
09468 ctype_unparse (ct),
09469 exprNode_unparse (e1), exprNode_unparse (e2)),
09470 e1->loc);
09471 }
09472
09473 sRefSet_realElements (aliases, ysr)
09474 {
09475 sRef base = sRef_getRootBase (ysr);
09476
09477 if (sRef_similar (ysr, s2b) || sRef_similar (s1b, base)
09478 || sRef_sameName (base, s1b))
09479 {
09480 ;
09481 }
09482 else
09483 {
09484 checkOneRepExpose (ysr, base, e1, e2, ct, s2b);
09485 }
09486 } end_sRefSet_realElements;
09487 }
09488 sRefSet_free (aliases);
09489 }
09490 }
09491
09492 donerepexpose:
09493
09494
09495
09496
09497
09498 if (!ctype_isFunction (ctype_realType (e2->typ)))
09499 {
09500 if (isInit)
09501 {
09502 checkInitTransfer (e1, e2);
09503 }
09504 else
09505 {
09506 checkAssignTransfer (e1, e2);
09507 }
09508 }
09509 else
09510 {
09511 sRef fref = e2->sref;
09512
09513 sRef_setDefState (e1->sref, sRef_getDefState (fref), e1->loc);
09514 sRef_setNullState (e1->sref, sRef_getNullState (fref), e1->loc);
09515
09516
09517
09518 if (ctype_isRealFunction (e1->typ)) {
09519 uentryList e1p = ctype_argsFunction (ctype_realType (e1->typ));
09520 uentryList e2p = ctype_argsFunction (ctype_realType (e2->typ));
09521
09522 if (!uentryList_isMissingParams (e1p)
09523 && !uentryList_isMissingParams (e2p)
09524 && uentryList_size (e1p) > 0) {
09525 if (uentryList_size (e1p) == uentryList_size (e2p)) {
09526 int n = 0;
09527
09528 uentryList_elements (e1p, el1) {
09529 uentry el2;
09530
09531 el2 = uentryList_getN (e2p, n);
09532 n++;
09533 uentry_checkMatchParam (el1, el2, n, e2);
09534 } end_uentryList_elements;
09535 }
09536 }
09537 }
09538 }
09539
09540 if (isInit && sRef_isGlobal (e1->sref))
09541 {
09542 ;
09543 }
09544 else
09545 {
09546 updateAliases (e1, e2);
09547 }
09548 }
09549
09550 static void
09551 checkMacroParen (exprNode e)
09552 {
09553 if (exprNode_isError (e) || e->kind == XPR_CAST)
09554 {
09555 ;
09556 }
09557 else
09558 {
09559 if (sRef_isUnsafe (e->sref) && !exprNode_isInParens (e))
09560 {
09561 voptgenerror
09562 (FLG_MACROPARENS,
09563 message ("Macro parameter used without parentheses: %s",
09564 exprNode_unparse (e)),
09565 e->loc);
09566 }
09567 }
09568 }
09569
09570 static void
09571 reflectNullTest ( exprNode e, bool isnull)
09572 {
09573 if (isnull)
09574 {
09575 e->guards = guardSet_addTrueGuard (e->guards, e->sref);
09576 }
09577 else
09578 {
09579 e->guards = guardSet_addFalseGuard (e->guards, e->sref);
09580 }
09581 }
09582
09583
09584
09585
09586
09587
09588
09589
09590
09591
09592
09593
09594
09595 static void updateAliases ( exprNode e1, exprNode e2)
09596 {
09597 if (!context_inProtectVars ())
09598 {
09599
09600
09601
09602
09603 sRef s1 = e1->sref;
09604 sRef s2 = e2->sref;
09605 ctype t1 = exprNode_getType (e1);
09606
09607
09608
09609 if (!ctype_isRealSU (t1))
09610 {
09611 sRef_copyRealDerivedComplete (s1, s2);
09612 }
09613
09614 if (ctype_isMutable (t1) && sRef_isKnown (s1))
09615 {
09616 usymtab_clearAlias (s1);
09617 usymtab_addMustAlias (s1, s2);
09618 }
09619
09620 if (sRef_possiblyNull (s1) && usymtab_isGuarded (s1))
09621 {
09622 usymtab_unguard (s1);
09623 }
09624 }
09625 }
09626
09627 exprNode exprNode_updateLocation ( exprNode e, fileloc loc)
09628 {
09629 if (exprNode_isDefined (e))
09630 {
09631 e->loc = fileloc_update (e->loc, loc);
09632 }
09633 else
09634 {
09635 e = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
09636 }
09637
09638 return (e);
09639 }
09640
09641 static void checkUniqueParams (exprNode fcn,
09642 exprNode current,
09643 exprNodeList args,
09644 int paramno, uentry ucurrent)
09645 {
09646 int iparamno = 0;
09647 sRef thisref = exprNode_getSref (current);
09648
09649
09650
09651
09652
09653 exprNodeList_elements (args, icurrent)
09654 {
09655 iparamno++;
09656
09657 if (iparamno != paramno)
09658 {
09659 sRef sr = exprNode_getSref (icurrent);
09660
09661 if (sRef_similarRelaxed (thisref, sr))
09662 {
09663 if (!sRef_isConst (thisref) && !sRef_isConst (sr))
09664 {
09665 voptgenerror
09666 (FLG_ALIASUNIQUE,
09667 message
09668 ("Parameter %d (%s) to function %s is declared %s but "
09669 "is aliased by parameter %d (%s)",
09670 paramno,
09671 exprNode_unparse (current),
09672 exprNode_unparse (fcn),
09673 alkind_unparse (uentry_getAliasKind (ucurrent)),
09674 iparamno, exprNode_unparse (icurrent)),
09675 current->loc);
09676 }
09677 }
09678 else
09679 {
09680 sRefSet aliases = usymtab_canAlias (sr);
09681
09682 sRefSet_allElements (aliases, asr)
09683 {
09684 if (ctype_isUnknown (sRef_getType (thisref)))
09685 {
09686 sRef_setType (thisref, uentry_getType (ucurrent));
09687 }
09688
09689 if (sRef_similarRelaxed (thisref, asr))
09690 {
09691 if (sRef_isExternal (asr))
09692 {
09693 if (sRef_isLocalState (thisref))
09694 {
09695 ;
09696 }
09697 else
09698 {
09699 sRef base = sRef_getRootBase (asr);
09700
09701 if (!sRef_similar (sRef_getBase (asr), thisref))
09702 {
09703 if (sRef_isUnique (base) || sRef_isOnly (base)
09704 || sRef_isKept (base)
09705 || (sRef_isAddress (asr) && sRef_isLocalVar (base))
09706 || (sRef_isAddress (thisref)
09707 && sRef_isLocalVar (sRef_getRootBase (thisref))))
09708 {
09709 ;
09710 }
09711 else
09712 {
09713 voptgenerror
09714 (FLG_MAYALIASUNIQUE,
09715 message
09716 ("Parameter %d (%s) to function %s is declared %s but "
09717 "may be aliased externally by parameter %d (%s)",
09718 paramno,
09719 exprNode_unparse (current),
09720 exprNode_unparse (fcn),
09721 alkind_unparse (uentry_getAliasKind (ucurrent)),
09722 iparamno, exprNode_unparse (icurrent)),
09723 current->loc);
09724 }
09725 }
09726 }
09727 }
09728 else
09729 {
09730 voptgenerror
09731 (FLG_ALIASUNIQUE,
09732 message
09733 ("Parameter %d (%s) to function %s is declared %s but "
09734 "is aliased externally by parameter %d (%s) through "
09735 "alias %q",
09736 paramno,
09737 exprNode_unparse (current),
09738 exprNode_unparse (fcn),
09739 alkind_unparse (uentry_getAliasKind (ucurrent)),
09740 iparamno, exprNode_unparse (icurrent),
09741 sRef_unparse (asr)),
09742 current->loc);
09743 }
09744 }
09745 } end_sRefSet_allElements;
09746 sRefSet_free (aliases);
09747 }
09748 }
09749 } end_exprNodeList_elements;
09750 }
09751
09752 long exprNode_getLongValue (exprNode e) {
09753 long value;
09754
09755 if (exprNode_hasValue (e)
09756 && multiVal_isInt (exprNode_getValue (e)))
09757 {
09758 value = multiVal_forceInt (exprNode_getValue (e));
09759 }
09760 else
09761 {
09762 value = 0;
09763 }
09764
09765 return value;
09766 }