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 "lclintMacros.nf"
00029 # include "basic.h"
00030
00031
00032 # define ATINVALID -1
00033
00034 static sRefSet
00035 aliasTable_canAliasAux (aliasTable p_s, sRef p_sr, int p_lim) ;
00036 static sRefSet
00037 aliasTable_aliasedByLimit (aliasTable p_s, sRef p_sr, int p_lim) ;
00038 static sRefSet
00039 aliasTable_aliasedByAux (aliasTable p_s, sRef p_sr, int p_lim) ;
00040
00041 aliasTable
00042 aliasTable_new ()
00043 {
00044 return (aliasTable_undefined);
00045 }
00046
00047 static aliasTable
00048 aliasTable_newEmpty (void)
00049 {
00050 aliasTable s = (aliasTable) dmalloc (sizeof (*s));
00051
00052 s->nelements = 0;
00053 s->nspace = aliasTableBASESIZE;
00054 s->keys = (sRef *) dmalloc (sizeof (*s->keys) * aliasTableBASESIZE);
00055 s->values = (sRefSet *) dmalloc (sizeof (*s->values) * aliasTableBASESIZE);
00056
00057 return (s);
00058 }
00059
00060 static void
00061 aliasTable_grow ( aliasTable s)
00062 {
00063 int i;
00064 o_sRefSet *oldvalues = s->values;
00065 sRef *oldkeys = s->keys;
00066
00067 s->nspace += aliasTableBASESIZE;
00068
00069 s->values = (sRefSet *) dmalloc (sizeof (*s->values)
00070 * (s->nelements + s->nspace));
00071 s->keys = (sRef *) dmalloc (sizeof (*s->keys) * (s->nelements + aliasTableBASESIZE));
00072
00073 if (s->keys == (sRef *) 0 || s->values == (sRefSet *)0)
00074 {
00075 llfatalerror (cstring_makeLiteral ("aliasTable_grow: out of memory!"));
00076 }
00077
00078 for (i = 0; i < s->nelements; i++)
00079 {
00080 s->values[i] = oldvalues[i];
00081 s->keys[i] = oldkeys[i];
00082 }
00083
00084 sfree (oldvalues);
00085 sfree (oldkeys);
00086 }
00087
00088 static int aliasTable_lookupRefs ( aliasTable s, sRef sr)
00089 {
00090 int i;
00091
00092
00093 for (i = 0; i < aliasTable_size (s); i++)
00094 {
00095 if (sRef_same (sr, s->keys[i]))
00096 {
00097 return i;
00098 }
00099 }
00100
00101 return ATINVALID;
00102 }
00103
00104
00105
00106
00107
00108 aliasTable
00109 aliasTable_addMustAlias ( aliasTable s,
00110 sRef sr,
00111 sRef al)
00112 {
00113 int ind;
00114 sRefSet ss;
00115
00116 llassert (NOALIAS (sr, al));
00117
00118 if (aliasTable_isUndefined (s))
00119 {
00120 s = aliasTable_newEmpty ();
00121 ind = ATINVALID;
00122 }
00123 else
00124 {
00125 ind = aliasTable_lookupRefs (s, sr);
00126 }
00127
00128 ss = aliasTable_canAlias (s, al);
00129
00130
00131 if (ind == ATINVALID)
00132 {
00133 if (s->nspace <= 0) {
00134 aliasTable_grow (s);
00135 }
00136
00137 s->nspace--;
00138 s->keys[s->nelements] = sr;
00139 s->values[s->nelements] = sRefSet_single (al);
00140 ind = s->nelements;
00141 s->nelements++;
00142 }
00143 else
00144 {
00145 s->values[ind] = sRefSet_insert (s->values[ind], al);
00146 }
00147
00148 s->values[ind] = sRefSet_unionExcept (s->values[ind], ss, s->keys[ind]);
00149
00150 sRefSet_free (ss);
00151 return s;
00152 }
00153
00154 static aliasTable
00155 aliasTable_addSet ( aliasTable s,
00156 sRef key, sRefSet value)
00157 {
00158 if (!sRefSet_isEmpty (value))
00159 {
00160 if (aliasTable_isUndefined (s))
00161 {
00162 s = aliasTable_newEmpty ();
00163 }
00164 else
00165 {
00166 if (s->nspace <= 0)
00167 {
00168 aliasTable_grow (s);
00169 }
00170 }
00171
00172 s->nspace--;
00173 s->keys[s->nelements] = key;
00174 s->values[s->nelements] = value;
00175 s->nelements++;
00176 }
00177 else
00178 {
00179 sRefSet_free (value);
00180 }
00181
00182 return s;
00183 }
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194 static void aliasTable_clearAliasesAux ( aliasTable p_s, sRef p_sr)
00195 ;
00196
00197 void aliasTable_clearAliases (aliasTable s, sRef sr)
00198 {
00199 if (aliasTable_isUndefined (s))
00200 {
00201 return;
00202 }
00203 else
00204 {
00205 sRef rb = sRef_getRootBase (sr);
00206
00207
00208 if (!sRef_isCvar (sr) && sRef_isLocalVar (rb))
00209 {
00210 int ind = aliasTable_lookupRefs (s, rb);
00211
00212 if (ind != ATINVALID)
00213 {
00214 sRefSet al = s->values[ind];
00215
00216
00217 sRefSet_realElements (al, el)
00218 {
00219
00220 if (sRef_isParam (el))
00221 {
00222 if (sRef_sameName (el, rb))
00223 {
00224 sRef fb = sRef_fixBase (sr, el);
00225
00226 aliasTable_clearAliasesAux (s, fb);
00227 }
00228 }
00229 } end_sRefSet_realElements ;
00230 }
00231 }
00232
00233 aliasTable_clearAliasesAux (s, sr);
00234 }
00235 }
00236
00237 static
00238 void aliasTable_clearAliasesAux ( aliasTable s, sRef sr)
00239 {
00240 int i;
00241
00242 for (i = 0; i < s->nelements; i++)
00243 {
00244 sRef key = s->keys[i];
00245
00246 if (sRef_includedBy (key, sr))
00247 {
00248 sRefSet_clear (s->values[i]);
00249 }
00250 else
00251 {
00252 (void) sRefSet_deleteBase (s->values[i], sr);
00253 }
00254 }
00255 }
00256
00257
00258
00259
00260
00261 static sRefSet aliasTable_aliasedByAux (aliasTable s, sRef sr, int lim)
00262 {
00263 static bool hadWarning = FALSE;
00264 sRefSet res = sRefSet_undefined;
00265 int i;
00266
00267 llassert (!sRef_isConj (sr));
00268
00269
00270 if (aliasTable_isUndefined (s) || lim >= ALIASSEARCHLIMIT)
00271 {
00272 if (lim >= ALIASSEARCHLIMIT && !hadWarning)
00273 {
00274 llquietbug
00275 (message ("Alias search limit exceeded, checking %q. "
00276 "This either means there is a variable with at least "
00277 "%d indirections, or there is a bug in LCLint.",
00278 sRef_unparse (sr),
00279 ALIASSEARCHLIMIT));
00280
00281 hadWarning = TRUE;
00282 }
00283
00284 return sRefSet_undefined;
00285 }
00286 else
00287 {
00288 sRefSet abl;
00289
00290 if (sRef_isPointer (sr))
00291 {
00292 abl = aliasTable_aliasedByLimit (s, sRef_getBase (sr), lim);
00293 res = sRefSet_addIndirection (abl);
00294 }
00295 else if (sRef_isAddress (sr))
00296 {
00297 abl = aliasTable_aliasedByLimit (s, sRef_getBase (sr), lim);
00298 res = sRefSet_removeIndirection (abl);
00299 }
00300 else if (sRef_isField (sr))
00301 {
00302 abl = aliasTable_aliasedByLimit (s, sRef_getBase (sr), lim);
00303 res = sRefSet_accessField (abl, sRef_getField (sr));
00304 }
00305 else if (sRef_isArrayFetch (sr))
00306 {
00307 abl = aliasTable_aliasedByLimit (s, sRef_getBase (sr), lim);
00308
00309 if (sRef_isIndexKnown (sr))
00310 {
00311 int idx = sRef_getIndex (sr);
00312
00313 res = sRefSet_fetchKnown (abl, idx);
00314 }
00315 else
00316 {
00317 res = sRefSet_fetchUnknown (abl);
00318 }
00319 }
00320 else
00321 {
00322 abl = sRefSet_undefined;
00323 }
00324
00325 sRefSet_free (abl);
00326 }
00327
00328 for (i = 0; i < s->nelements; i++)
00329 {
00330 sRef elem = s->keys[i];
00331
00332 if (!sRef_same (sr, elem))
00333 {
00334
00335 sRefSet_realElements (s->values[i], current)
00336 {
00337
00338 if (sRef_similar (sr, current))
00339 {
00340 res = sRefSet_insert (res, sRef_fixOuterRef (elem));
00341 break;
00342 }
00343 } end_sRefSet_realElements;
00344 }
00345 }
00346
00347 return res;
00348 }
00349
00350 static sRefSet aliasTable_aliasedByLimit (aliasTable s, sRef sr, int lim)
00351 {
00352 sRefSet res;
00353
00354
00355 if (sRef_isConj (sr))
00356 {
00357 res = sRefSet_unionFree (aliasTable_aliasedByLimit (s, sRef_getConjA (sr), lim),
00358 aliasTable_aliasedByLimit (s, sRef_getConjB (sr), lim));
00359 }
00360 else
00361 {
00362 res = aliasTable_aliasedByAux (s, sr, lim + 1);
00363 }
00364
00365 return res;
00366 }
00367
00368 sRefSet aliasTable_aliasedBy (aliasTable s, sRef sr)
00369 {
00370 if (sRef_isConj (sr))
00371 {
00372 return (sRefSet_unionFree (aliasTable_aliasedBy (s, sRef_getConjA (sr)),
00373 aliasTable_aliasedBy (s, sRef_getConjB (sr))));
00374 }
00375
00376 return (aliasTable_aliasedByAux (s, sr, 0));
00377 }
00378
00379 sRefSet aliasTable_canAlias (aliasTable s, sRef sr)
00380 {
00381 sRefSet res;
00382
00383
00384 if (sRef_isConj (sr))
00385 {
00386 res = sRefSet_unionFree (aliasTable_canAlias (s, sRef_getConjA (sr)),
00387 aliasTable_canAlias (s, sRef_getConjB (sr)));
00388 }
00389 else
00390 {
00391 res = aliasTable_canAliasAux (s, sr, 0);
00392 }
00393
00394 return res;
00395 }
00396
00397
00398
00399
00400
00401 static sRefSet aliasTable_canAliasLimit (aliasTable s, sRef sr, int lim)
00402 {
00403 sRefSet res;
00404
00405 if (sRef_isConj (sr))
00406 {
00407 sRefSet a = aliasTable_canAliasLimit (s, sRef_getConjA (sr), lim);
00408 sRefSet b = aliasTable_canAliasLimit (s, sRef_getConjB (sr), lim);
00409
00410 res = sRefSet_unionFree (a, b);
00411 }
00412 else
00413 {
00414 res = aliasTable_canAliasAux (s, sr, lim + 1);
00415 }
00416
00417 return res;
00418 }
00419
00420 static sRefSet
00421 aliasTable_canAliasAux (aliasTable s, sRef sr, int lim)
00422 {
00423 static bool hadWarning = FALSE;
00424 llassert (!sRef_isConj (sr));
00425
00426
00427 if (aliasTable_isUndefined (s) || lim >= ALIASSEARCHLIMIT)
00428 {
00429 if (lim >= ALIASSEARCHLIMIT && !hadWarning)
00430 {
00431 llquietbug
00432 (message ("Alias search limit exceeded, checking %q. "
00433 "This either means there is a variable with at least "
00434 "%d indirections, or there is a bug in LCLint.",
00435 sRef_unparse (sr),
00436 ALIASSEARCHLIMIT));
00437
00438 hadWarning = TRUE;
00439 }
00440
00441 return sRefSet_undefined;
00442 }
00443 else
00444 {
00445 int ind = aliasTable_lookupRefs (s, sr);
00446
00447 if (sRef_isPointer (sr) || sRef_isAddress (sr) || sRef_isField (sr)
00448 || sRef_isArrayFetch (sr))
00449 {
00450 sRef base = sRef_getBase (sr);
00451 sRefSet tmp = aliasTable_canAliasLimit (s, base, lim);
00452 sRefSet ret;
00453
00454 if (sRef_isPointer (sr))
00455 {
00456 ret = sRefSet_addIndirection (tmp);
00457 }
00458 else if (sRef_isAddress (sr))
00459 {
00460 ret = sRefSet_removeIndirection (tmp);
00461 }
00462 else if (sRef_isField (sr))
00463 {
00464 ret = sRefSet_accessField (tmp, sRef_getField (sr));
00465 }
00466 else if (sRef_isArrayFetch (sr))
00467 {
00468 if (sRef_isIndexKnown (sr))
00469 {
00470 ret = sRefSet_fetchKnown (tmp, sRef_getIndex (sr));
00471 }
00472 else
00473 {
00474 ret = sRefSet_fetchUnknown (tmp);
00475 }
00476 }
00477 else
00478 {
00479 BADBRANCH;
00480 }
00481
00482 if (ind != ATINVALID)
00483 {
00484 ret = sRefSet_union (ret, s->values[ind]);
00485 }
00486
00487 sRefSet_free (tmp);
00488 return ret;
00489 }
00490
00491 if (ind == ATINVALID) return sRefSet_undefined;
00492
00493 return sRefSet_newCopy (s->values[ind]);
00494 }
00495 }
00496
00497 aliasTable aliasTable_copy (aliasTable s)
00498 {
00499 if (aliasTable_isEmpty (s))
00500 {
00501 return aliasTable_undefined;
00502 }
00503 else
00504 {
00505 aliasTable t = (aliasTable) dmalloc (sizeof (*s));
00506 int i;
00507
00508 t->nelements = s->nelements;
00509 t->nspace = 0;
00510 t->keys = (sRef *) dmalloc (sizeof (*s->keys) * s->nelements);
00511 t->values = (sRefSet *) dmalloc (sizeof (*s->values) * t->nelements);
00512
00513 for (i = 0; i < s->nelements; i++)
00514 {
00515 t->keys[i] = s->keys[i];
00516 t->values[i] = sRefSet_newCopy (s->values[i]);
00517 }
00518
00519 return t;
00520 }
00521 }
00522
00523 static void
00524 aliasTable_levelPrune (aliasTable s, int lexlevel)
00525 {
00526
00527
00528 if (aliasTable_isEmpty (s))
00529 {
00530 return;
00531 }
00532 else
00533 {
00534 int i;
00535 int backcount = s->nelements - 1;
00536
00537 for (i = 0; i <= backcount; i++)
00538 {
00539 sRef key = s->keys[i];
00540
00541 if (sRef_lexLevel (key) > lexlevel)
00542 {
00543 int j;
00544 for (j = backcount; j > i; j--)
00545 {
00546 backcount--;
00547 s->nelements--;
00548 s->nspace++;
00549
00550 if (sRef_lexLevel (s->keys[j]) <= lexlevel)
00551 {
00552 s->keys[i] = s->keys[j];
00553 s->values[i] = s->values[j];
00554 sRefSet_levelPrune (s->values[i], lexlevel);
00555 break;
00556 }
00557 }
00558 if (backcount == i)
00559 s->nelements--;
00560 }
00561 else
00562 {
00563 sRefSet_levelPrune (s->values[i], lexlevel);
00564 }
00565 }
00566 }
00567 }
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578 aliasTable aliasTable_levelUnionSeq ( aliasTable t1,
00579 aliasTable t2, int level)
00580 {
00581 if (aliasTable_isUndefined (t2))
00582 {
00583 return t1;
00584 }
00585
00586 if (aliasTable_isUndefined (t1))
00587 {
00588 t1 = aliasTable_newEmpty ();
00589 }
00590 else
00591 {
00592 aliasTable_levelPrune (t1, level);
00593 }
00594
00595 aliasTable_elements (t2, key, value)
00596 {
00597 if (sRef_lexLevel (key) <= level)
00598 {
00599 int ind = aliasTable_lookupRefs (t1, key);
00600
00601 sRefSet_levelPrune (value, level);
00602
00603 if (ind == ATINVALID)
00604 {
00605
00606
00607 t1 = aliasTable_addSet (t1, key, value);
00608
00609 }
00610 else
00611 {
00612 sRefSet_free (t1->values[ind]);
00613
00614
00615 t1->values[ind] = value;
00616
00617 }
00618 }
00619 else
00620 {
00621
00622 sRefSet_free (value);
00623
00624 }
00625
00626 } end_aliasTable_elements;
00627
00628 sfree (t2->keys);
00629 sfree (t2->values);
00630 sfree (t2);
00631
00632 return t1;
00633 }
00634
00635 aliasTable
00636 aliasTable_levelUnion ( aliasTable t1, aliasTable t2, int level)
00637 {
00638 if (aliasTable_isUndefined (t1))
00639 {
00640 if (aliasTable_isUndefined (t2))
00641 {
00642 return t1;
00643 }
00644 else
00645 {
00646 t1 = aliasTable_newEmpty ();
00647 }
00648 }
00649 else
00650 {
00651 aliasTable_levelPrune (t1, level);
00652 }
00653
00654 aliasTable_elements (t2, key, cvalue)
00655 {
00656 sRefSet value = sRefSet_newCopy (cvalue);
00657
00658 if (sRef_lexLevel (key) <= level)
00659 {
00660 sRefSet_levelPrune (value, level);
00661
00662 if (sRefSet_size (value) > 0)
00663 {
00664 int ind = aliasTable_lookupRefs (t1, key);
00665
00666 if (ind == ATINVALID)
00667 {
00668 t1 = aliasTable_addSet (t1, key, value);
00669 }
00670 else
00671 {
00672 t1->values[ind] = sRefSet_union (t1->values[ind], value);
00673 sRefSet_free (value);
00674 }
00675 }
00676 else
00677 {
00678 sRefSet_free (value);
00679 }
00680 }
00681 else
00682 {
00683 sRefSet_free (value);
00684 }
00685 } end_aliasTable_elements;
00686
00687 return t1;
00688 }
00689
00690 aliasTable aliasTable_levelUnionNew (aliasTable t1, aliasTable t2, int level)
00691 {
00692 aliasTable ret = aliasTable_levelUnion (aliasTable_copy (t1), t2, level);
00693
00694 return ret;
00695 }
00696
00697 cstring
00698 aliasTable_unparse (aliasTable s)
00699 {
00700 cstring st = cstring_undefined;
00701
00702 if (aliasTable_isUndefined (s)) return (cstring_makeLiteral ("<NULL>"));
00703
00704 aliasTable_elements (s, key, value)
00705 {
00706 st = message ("%q\t%q -> %q\n", st, sRef_unparse (key),
00707 sRefSet_unparse (value));
00708 } end_aliasTable_elements;
00709
00710 return st;
00711 }
00712
00713
00714
00715
00716
00717 void
00718 aliasTable_fixSrefs (aliasTable s)
00719 {
00720 int i;
00721
00722 if (aliasTable_isUndefined (s)) return;
00723
00724 for (i = 0; i < s->nelements; i++)
00725 {
00726 sRef old = s->keys[i];
00727
00728 if (sRef_isLocalVar (old))
00729 {
00730 s->keys[i] = uentry_getSref (sRef_getUentry (old));
00731 }
00732
00733 sRefSet_fixSrefs (s->values[i]);
00734 }
00735 }
00736
00737 void
00738 aliasTable_free ( aliasTable s)
00739 {
00740 int i;
00741
00742 if (aliasTable_isUndefined (s)) return;
00743
00744 for (i = 0; i < s->nelements; i++)
00745 {
00746 sRefSet_free (s->values[i]);
00747 }
00748
00749 sfree (s->values);
00750 sfree (s->keys);
00751 sfree (s);
00752 }
00753
00754 void
00755 aliasTable_checkGlobs (aliasTable t)
00756 {
00757 aliasTable_elements (t, key, value)
00758 {
00759 sRef root = sRef_getRootBase (key);
00760
00761 if (sRef_isAliasCheckedGlobal (root))
00762 {
00763 sRefSet_realElements (value, sr)
00764 {
00765 root = sRef_getRootBase (sr);
00766
00767 if (((sRef_isAliasCheckedGlobal (root)
00768 && !(sRef_similar (root, key)))
00769 || sRef_isAnyParam (root))
00770 && !sRef_isExposed (root))
00771 {
00772 if (sRef_isAliasCheckedGlobal (key))
00773 {
00774 if (!(sRef_isShared (key)
00775 && sRef_isShared (root)))
00776 {
00777 voptgenerror
00778 (FLG_GLOBALIAS,
00779 message
00780 ("Function returns with %q variable %q aliasing %q %q",
00781 cstring_makeLiteral (sRef_isRealGlobal (key)
00782 ? "global" : "file static"),
00783 sRef_unparse (key),
00784 cstring_makeLiteral (sRef_isAnyParam (root)
00785 ? "parameter" : "global"),
00786 sRef_unparse (sr)),
00787 g_currentloc);
00788 }
00789 }
00790
00791 }
00792 } end_sRefSet_realElements;
00793 }
00794 else if (sRef_isAnyParam (key) || sRef_isAnyParam (root))
00795 {
00796 sRefSet_realElements (value, sr)
00797 {
00798 root = sRef_getRootBase (sr);
00799
00800 if (sRef_isAliasCheckedGlobal (root)
00801 && !sRef_isExposed (root)
00802 && !sRef_isDead (key)
00803 && !sRef_isShared (root))
00804 {
00805 voptgenerror
00806 (FLG_GLOBALIAS,
00807 message ("Function returns with parameter %q aliasing %q %q",
00808 sRef_unparse (key),
00809 cstring_makeLiteral (sRef_isRealGlobal (root)
00810 ? "global" : "file static"),
00811 sRef_unparse (sr)),
00812 g_currentloc);
00813 }
00814 } end_sRefSet_realElements;
00815 }
00816 else
00817 {
00818 ;
00819 }
00820 } end_aliasTable_elements;
00821 }
00822
00823
00824