Main Page   Alphabetical List   Compound List   File List   Compound Members   File Members  

uentry.c

Go to the documentation of this file.
00001 /*
00002 ** LCLint - annotation-assisted static program checker
00003 ** Copyright (C) 1994-2000 University of Virginia,
00004 **         Massachusetts Institute of Technology
00005 **
00006 ** This program is free software; you can redistribute it and/or modify it
00007 ** under the terms of the GNU General Public License as published by the
00008 ** Free Software Foundation; either version 2 of the License, or (at your
00009 ** option) any later version.
00010 ** 
00011 ** This program is distributed in the hope that it will be useful, but
00012 ** WITHOUT ANY WARRANTY; without even the implied warranty of
00013 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 ** General Public License for more details.
00015 ** 
00016 ** The GNU General Public License is available from http://www.gnu.org/ or
00017 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00018 ** MA 02111-1307, USA.
00019 **
00020 ** For information on lclint: lclint-request@cs.virginia.edu
00021 ** To report a bug: lclint-bug@cs.virginia.edu
00022 ** For more information: http://lclint.cs.virginia.edu
00023 */
00024 /*
00025 ** uentry.c
00026 */
00027 
00028 # include "lclintMacros.nf"
00029 # include "basic.h"
00030 # include "structNames.h"
00031 # include "nameChecks.h"
00032 
00033 static /*@dependent@*/ uentry posRedeclared = uentry_undefined;
00034 static /*@only@*/ fileloc posLoc = fileloc_undefined;
00035 static int nuentries = 0;
00036 static int totuentries = 0;
00037 
00038 static void checkGlobalsModifies (/*@notnull@*/ uentry p_ue, sRefSet p_sr) ;
00039 static void uentry_setDeclDef (uentry p_e, fileloc p_f) /*@modifies p_e@*/ ;
00040 static bool uentry_isRefCounted (uentry p_ue) /*@*/ ;
00041 static bool uentry_isRefsField (uentry p_ue) /*@*/ ;
00042 static bool uentry_isReallySpecified (uentry p_e) /*@*/ ;
00043 static void uentry_checkIterArgs (uentry p_ue);
00044 static cstring uentry_dumpAux (uentry p_v, bool p_isParam);
00045 
00046 /*@access ekind@*/
00047 static void checkAliasState (/*@notnull@*/ uentry p_old,
00048                                /*@notnull@*/ uentry p_unew, 
00049                                bool p_mustConform, bool p_completeConform) 
00050    /*@modifies p_old, p_unew@*/ ;
00051 static void checkNullState (/*@notnull@*/ uentry p_old,
00052                             /*@notnull@*/ uentry p_unew, 
00053                             bool p_mustConform, bool p_completeConform) 
00054    /*@modifies p_old, p_unew@*/ ;
00055 
00056 static void checkVarConformance (/*@notnull@*/ uentry p_old,
00057                                  /*@notnull@*/ uentry p_unew, 
00058                                  bool p_mustConform, bool p_completeConform) 
00059    /*@modifies p_old, p_unew@*/;
00060 
00061 # ifndef NOLCL
00062 static void uentry_setHasMods (uentry p_ue) /*@modifies p_ue@*/;
00063 static void uentry_setHasGlobs (uentry p_ue) /*@modifies p_ue@*/;
00064 # endif
00065 
00066 static void uentry_reallyFree (/*@notnull@*/ /*@only@*/ uentry p_e);
00067 
00068 static void uentry_setSpecDef (/*@special@*/ uentry p_e, /*@keep@*/ fileloc p_f)
00069    /*@defines p_e->whereSpecified, p_e->whereDeclared, p_e->whereDefined@*/
00070    /*@modifies p_e@*/;
00071 
00072 static void returnValueError (/*@notnull@*/ uentry p_old, /*@notnull@*/ uentry p_unew);
00073 static void nargsError (/*@notnull@*/ uentry p_old, /*@notnull@*/ uentry p_unew);
00074 static /*@observer@*/ cstring paramStorageName (uentry p_ue) /*@*/ ;
00075 static /*@observer@*/ cstring fcnErrName (uentry p_ue) /*@*/ ;
00076 static /*@observer@*/ cstring checkedName (chkind p_checked) /*@*/ ;
00077 static void 
00078   paramTypeError (/*@notnull@*/ uentry p_old, /*@notnull@*/ uentry p_oldCurrent,
00079                   ctype p_oldType, /*@notnull@*/ uentry p_unew,
00080                   /*@notnull@*/ uentry p_newCurrent, 
00081                   ctype p_newType, int p_paramno) /*@modifies g_msgstream@*/ ;
00082 
00083 static /*@only@*/ /*@notnull@*/ uentry 
00084   uentry_makeVariableAux (cstring p_n, ctype p_t, /*@keep@*/ fileloc p_f,
00085                           /*@exposed@*/ sRef p_s, bool p_priv, vkind p_kind);
00086 
00087 static /*@out@*/ /*@notnull@*/ uentry uentry_alloc (void) /*@*/ 
00088 {
00089   uentry ue = (uentry) dmalloc (sizeof (*ue));
00090   nuentries++;
00091   totuentries++;
00092   
00093   return ue;
00094 }
00095 
00096 static cstring uentry_getOptName (uentry p_e) /*@*/ ;
00097 static void uentry_copyInto (/*@out@*/ /*@unique@*/ uentry p_unew, uentry p_old);
00098 static void uentry_setNullState (/*@notnull@*/ uentry p_ue, nstate p_ns);
00099 static void uentry_setAliasKind (/*@notnull@*/ uentry p_ue, alkind p_ak);
00100 static /*@only@*/ /*@null@*/ uinfo uinfo_copy (uinfo p_u, ekind p_kind);
00101 static void uinfo_free (/*@only@*/ uinfo p_u, ekind p_kind);
00102 static void uvinfo_free (/*@only@*/ uvinfo p_u);
00103 
00104 # ifdef DOANNOTS
00105 
00106 static /*@only@*/ cstring ancontext_unparse (ancontext an)
00107 {
00108   switch (an)
00109     {
00110     case AN_UNKNOWN: return cstring_makeLiteral ("unknown");
00111     case AN_FCNRETURN: return cstring_makeLiteral ("return value");
00112     case AN_FCNPARAM: return cstring_makeLiteral ("function param");
00113     case AN_SUFIELD: return cstring_makeLiteral ("su field");
00114     case AN_TDEFN: return cstring_makeLiteral ("type definition");
00115     case AN_GSVAR: return cstring_makeLiteral ("global/static var");
00116     case AN_CONST: return cstring_makeLiteral ("constant");
00117     BADDEFAULT;
00118     }
00119   BADEXIT;
00120 }
00121 
00122 static int annots[AN_LAST][QU_LAST];
00123 static int decls[AN_LAST];
00124 static int shdecls[AN_LAST];
00125 static int idecls[AN_LAST];
00126 
00127 void initAnnots ()
00128 {
00129   int i, j;
00130 
00131   for (i = AN_UNKNOWN; i < AN_LAST; i++)
00132     {
00133       decls[i] = 0;
00134       shdecls[i] = 0;
00135       idecls[i] = 0;
00136 
00137       for (j = QU_UNKNOWN; j < QU_LAST; j++)
00138         {
00139           annots[i][j] = 0;
00140         }
00141     }
00142 }
00143 
00144 static void tallyAnnot (ancontext ac, qual q)
00145 {
00146   (annots[ac][q])++;
00147 }
00148 
00149 void printAnnots ()
00150 {
00151   int total[QU_LAST];
00152   int alltotals = 0;
00153   int totdecls = 0;
00154   int totshdecls = 0;
00155   int totidecls = 0;
00156   int i, j;
00157 
00158   for (j = QU_UNKNOWN; j < QU_LAST; j++)
00159     {
00160       total[j] = 0;
00161     }
00162 
00163   for (i = AN_UNKNOWN; i < AN_LAST; i++)
00164     {
00165       int tmptot;
00166 
00167       if (decls[i] > 0)
00168         {
00169           printf ("Context: %s (%d declarations, %d sharable, %d indirect)\n", 
00170                   ancontext_unparse (i),
00171                   decls[i], shdecls[i], idecls[i]);
00172           
00173           totdecls += decls[i];
00174           totshdecls += shdecls[i];
00175           totidecls += idecls[i];
00176           
00177           for (j = QU_UNKNOWN; j < QU_LAST; j++)
00178             {
00179               total[j] += annots[i][j];
00180               alltotals += annots[i][j];
00181             }
00182           
00183           printf ("   Allocation:\n");
00184           
00185           tmptot = 0;
00186           
00187           for (j = QU_UNKNOWN; j < QU_LAST; j++)
00188             {
00189               if (qual_isAliasQual (j) && !qual_isUnique (j))
00190                 {
00191                   if (annots[i][j] > 0)
00192                     {
00193                       printf ("\t%10s: %5d (%3.2f%%)\n", qual_unparse (j), annots[i][j],
00194                               100.0 * (double)annots[i][j] / (double)decls[i]);
00195                       tmptot += annots[i][j];
00196                     }
00197                 }
00198             }
00199 
00200           printf ("   Exposure:\n");
00201           
00202           tmptot = 0;
00203           
00204           for (j = QU_UNKNOWN; j < QU_LAST; j++)
00205             {
00206               if (qual_isExQual (j))
00207                 {
00208                   if (annots[i][j] > 0)
00209                     {
00210                       printf ("\t%10s: %5d (%3.2f%%)\n", qual_unparse (j), annots[i][j],
00211                               100.0 * (double)annots[i][j] / (double)decls[i]);
00212                       tmptot += annots[i][j];
00213                     }
00214                 }
00215             }
00216           
00217           printf ("   Definition:\n");
00218           
00219           for (j = QU_UNKNOWN; j < QU_LAST; j++)
00220             {
00221               if (qual_isAllocQual (j))
00222                 {
00223                   if (annots[i][j] > 0)
00224                     {
00225                       printf ("\t%10s: %5d (%3.2f%%)\n", qual_unparse (j), annots[i][j],
00226                               100.0 * (double)annots[i][j] / (double)decls[i]);
00227                     }
00228                 }
00229             }
00230           
00231           printf ("   Null:\n");
00232           
00233           for (j = QU_UNKNOWN; j < QU_LAST; j++)
00234             {
00235               if (qual_isNull (j) || qual_isNotNull (j) || qual_isRelNull (j))
00236                 {
00237                   if (annots[i][j] > 0)
00238                     {
00239                       printf ("\t%10s: %5d (%3.2f%%)\n", qual_unparse (j), annots[i][j],
00240                               100.0 * (double)annots[i][j] / (double)decls[i]);
00241                     }
00242                 }
00243             }
00244 
00245           printf ("\n");
00246         }
00247     }
00248 
00249   for (j = QU_UNKNOWN; j < QU_LAST; j++)
00250     {
00251       bool hasone = FALSE;
00252 
00253       for (i = AN_UNKNOWN; i < AN_LAST; i++)
00254         {
00255           if (annots[i][j] > 0)
00256             {
00257               hasone = TRUE;
00258               break;
00259             }
00260         }
00261 
00262       if (hasone)
00263         {
00264           printf ("Annotation: %s\n", qual_unparse (j));
00265           
00266           for (i = AN_UNKNOWN; i < AN_LAST; i++)
00267             {
00268               if (annots[i][j] > 0)
00269                 {
00270                   printf ("%25s: %5d\n", ancontext_unparse (i), annots[i][j]);
00271                 }
00272             }
00273           printf ("\n");
00274         }
00275     }
00276 
00277   printf ("All Contexts\n");
00278   
00279   for (j = QU_UNKNOWN; j < QU_LAST; j++)
00280     {
00281       if (total[j] > 0)
00282         {
00283           printf ("%10s: %5d (%3.2f%%)\n", qual_unparse (j), total[j],
00284                   100.0 * (double)total[j] / (double)(totdecls));
00285         }
00286     }
00287   printf ("\n");
00288 
00289   printf ("Total Annotations: %d (%d decls, %d sharable, %d indirect)\n", alltotals, totdecls, totshdecls, totidecls); }
00290 
00291 extern void uentry_tallyAnnots (uentry u, ancontext kind)
00292 {
00293   alkind ak = sRef_getAliasKind (u->sref);
00294   exkind ek = sRef_getExKind (u->sref);
00295   nstate ns = sRef_getNullState (u->sref);
00296   sstate ss = sRef_getDefState (u->sref);
00297   bool recordUnknown = FALSE;
00298 
00299   
00300   if (kind == AN_UNKNOWN)
00301     {
00302       ekind e = u->ukind;
00303 
00304       if (e == KENDITER)
00305         {
00306           return;
00307         }
00308       else if (e == KCONST || e == KENUMCONST)
00309         {
00310           kind = AN_CONST;
00311         }
00312       else if (e == KFCN || e == KITER)
00313         {
00314           uentryList params = uentry_getParams (u);
00315           bool hasRet = FALSE;
00316 
00317           uentryList_elements (params, current)
00318             {
00319               if (uentry_isReturned (current))
00320                 {
00321                   hasRet = TRUE;
00322                 }
00323               if (!uentry_isElipsisMarker (current))
00324                 {
00325                   uentry_tallyAnnots (current, AN_FCNPARAM);
00326                 }
00327             } end_uentryList_elements;
00328           
00329           kind = AN_FCNRETURN;
00330           
00331           if (ctype_isFunction (u->utype)
00332               && !hasRet
00333               && ctype_isVisiblySharable (ctype_realType (ctype_returnValue (u->utype))))
00334             {
00335               recordUnknown = TRUE;
00336             }
00337         }
00338       else if (e == KDATATYPE || e == KSTRUCTTAG || e == KUNIONTAG || e == KENUMTAG)
00339         {
00340           ctype t = ctype_realType (u->utype);
00341 
00342           if (ctype_isSU (t))
00343             {
00344               uentryList fields = ctype_getFields (t);
00345 
00346               uentryList_elements (fields, current)
00347                 {
00348                   uentry_tallyAnnots (current, AN_SUFIELD);
00349                 }
00350             } end_uentryList_elements;
00351           
00352           kind = AN_TDEFN;
00353 
00354           if (ctype_isVisiblySharable (u->utype))
00355             {
00356               recordUnknown = TRUE;
00357             }
00358         }
00359       else 
00360         {
00361           kind = AN_GSVAR;
00362           
00363           
00364           if (ctype_isVisiblySharable (ctype_realType (u->utype)))
00365             {
00366               recordUnknown = TRUE;
00367             }
00368         }
00369     }
00370 
00371   decls[kind]++;
00372 
00373   if (kind == AN_FCNRETURN)
00374     {
00375       if (recordUnknown) 
00376         {
00377           shdecls[kind]++;
00378           idecls[kind]++;
00379         }
00380       else 
00381         {
00382           ;
00383         }
00384     }
00385   else
00386     {
00387       if (ctype_isVisiblySharable (ctype_realType (u->utype)))
00388         {
00389           shdecls[kind]++;
00390                 }
00391       
00392       if (ctype_isRealPointer (ctype_realType (u->utype)))
00393         {
00394           idecls[kind]++;
00395         }
00396     }
00397   
00398 
00399 
00400 
00401 
00402 
00403 
00404 
00405 
00406 
00407   switch (ss)
00408     {
00409     case SS_ALLOCATED: tallyAnnot (kind, QU_OUT); break;
00410     case SS_PARTIAL:   tallyAnnot (kind, QU_PARTIAL); break;
00411     case SS_RELDEF:    tallyAnnot (kind, QU_RELDEF); break;
00412     case SS_SPECIAL:   tallyAnnot (kind, QU_SPECIAL); break;
00413     default: break;
00414     }
00415 
00416   if (uentry_isReturned (u))
00417     {
00418       tallyAnnot (kind, QU_RETURNED); 
00419     }
00420 
00421   switch (ak)
00422     {
00423     case AK_UNKNOWN:    
00424       if (ctype_isRefCounted (ctype_realType (u->utype))
00425           || (ctype_isFunction (u->utype) &&
00426               ctype_isRefCounted (ctype_realType (ctype_returnValue (u->utype)))))
00427         {
00428           ;
00429         }
00430       else
00431         {
00432           if (kind == AN_FCNPARAM) 
00433             { 
00434               tallyAnnot (kind, QU_TEMP); 
00435             } 
00436           else if (recordUnknown) 
00437             { 
00438               if (kind == AN_FCNRETURN)
00439                 {
00440                                 }
00441               tallyAnnot (kind, QU_UNKNOWN); 
00442             }
00443         }
00444       break;
00445     case AK_ONLY:       tallyAnnot (kind, QU_ONLY); break;
00446     case AK_IMPONLY:    tallyAnnot (kind, QU_ONLY); break;
00447     case AK_KEEP:       tallyAnnot (kind, QU_KEEP); break;
00448     case AK_KEPT:       tallyAnnot (kind, QU_KEPT); break;
00449     case AK_IMPTEMP:
00450     case AK_TEMP:       tallyAnnot (kind, QU_TEMP); break;
00451     case AK_SHARED:     tallyAnnot (kind, QU_SHARED); break;
00452     case AK_UNIQUE:     tallyAnnot (kind, QU_UNIQUE); break;
00453     case AK_RETURNED:   tallyAnnot (kind, QU_RETURNED); break;
00454     case AK_REFCOUNTED: tallyAnnot (kind, QU_UNKNOWN); break;
00455     case AK_REFS:       tallyAnnot (kind, QU_REFS); break;
00456     case AK_KILLREF:    tallyAnnot (kind, QU_KILLREF); break;
00457     case AK_NEWREF:     tallyAnnot (kind, QU_NEWREF); break;
00458     case AK_OWNED:      tallyAnnot (kind, QU_OWNED); break;
00459     case AK_IMPDEPENDENT:
00460     case AK_DEPENDENT:  tallyAnnot (kind, QU_DEPENDENT); break;
00461     case AK_ERROR:    
00462     case AK_FRESH:
00463     case AK_STACK:
00464     case AK_LOCAL:
00465       break;
00466     }
00467 
00468   switch (ek)
00469     {
00470     case XO_EXPOSED:    tallyAnnot (kind, QU_EXPOSED); break;
00471     case XO_OBSERVER:   tallyAnnot (kind, QU_OBSERVER); break;
00472     default:  break;
00473     }
00474 
00475   switch (ns)
00476     {
00477     case NS_ERROR:   break;
00478     case NS_UNKNOWN:   break;
00479     case NS_NOTNULL:   break;
00480     case NS_MNOTNULL:  tallyAnnot (kind, QU_NOTNULL); break;
00481     case NS_RELNULL:   tallyAnnot (kind, QU_RELNULL); break;
00482     case NS_CONSTNULL: tallyAnnot (kind, QU_NULL); break;
00483     case NS_POSNULL:   tallyAnnot (kind, QU_NULL); break;
00484     case NS_DEFNULL: 
00485     case NS_ABSNULL:   break;   
00486     }
00487 }
00488 
00489 # endif
00490 
00491 static /*@observer@*/ cstring specCode_unparse (specCode s) /*@*/
00492 {
00493   switch (s)
00494     {
00495     case SPC_NONE: return cstring_makeLiteralTemp ("normal");
00496     case SPC_PRINTFLIKE: return cstring_makeLiteralTemp ("printflike");
00497     case SPC_SCANFLIKE: return cstring_makeLiteralTemp ("scanflike");
00498     case SPC_MESSAGELIKE: return cstring_makeLiteralTemp ("messagelike");
00499     case SPC_LAST: return cstring_makeLiteralTemp ("<error>");
00500     }
00501 
00502   BADEXIT;
00503 }
00504 
00505 static specCode specCode_fromInt (int i)
00506 {
00507   /*@+enumint@*/
00508   llassert (i >= SPC_NONE && i < SPC_LAST);
00509 
00510   return ((specCode) i);
00511   /*@=enumint@*/
00512 }
00513 
00514 /*@observer@*/ cstring uentry_specOrDefName (uentry u) 
00515 {
00516   if (uentry_isDeclared (u))
00517     {
00518       return cstring_makeLiteralTemp ("previously declared");
00519     }
00520   else
00521     {
00522       return cstring_makeLiteralTemp ("specified");
00523     }
00524 }
00525 
00526 /*@observer@*/ cstring uentry_specDeclName (uentry u) 
00527 {
00528   if (uentry_isDeclared (u))
00529     {
00530       return cstring_makeLiteralTemp ("previous declaration");
00531     }
00532   else
00533     {
00534       return cstring_makeLiteralTemp ("specification");
00535     }
00536 }
00537 
00538 static /*@observer@*/ cstring uentry_reDefDecl (uentry old, uentry unew)  /*@*/ 
00539 {
00540   if (uentry_isCodeDefined (old) && uentry_isCodeDefined (unew))
00541     {
00542       return cstring_makeLiteralTemp ("redefined");
00543     }
00544   else if (uentry_isCodeDefined (unew))
00545     {
00546       return cstring_makeLiteralTemp ("defined");
00547     }
00548   else if (uentry_isDeclared (old) && uentry_isDeclared (unew))
00549     {
00550       return cstring_makeLiteralTemp ("redeclared");
00551     }
00552   else
00553     {
00554       return cstring_makeLiteralTemp ("declared");
00555     }
00556 }
00557 
00558 static /*@only@*/ fileloc setLocation (void)
00559 {
00560   fileloc fl = context_getSaveLocation ();
00561 
00562   if (fileloc_isDefined (fl)) 
00563     {
00564       return fl;
00565     }
00566   else
00567     {
00568       return fileloc_copy (g_currentloc);
00569     }
00570 }
00571 
00572 /*@notnull@*/ uentry uentry_makeEnumConstant (cstring n, ctype t)
00573 {
00574   fileloc loc = setLocation ();
00575   uentry ue = uentry_makeConstant (n, t, loc);
00576 
00577   ue->ukind = KENUMCONST;
00578   uentry_setDefined (ue, loc);
00579   return ue;
00580 }
00581 
00582 /*@notnull@*/ uentry uentry_makeEnumInitializedConstant (cstring n, ctype t, exprNode expr)
00583 {
00584   fileloc loc = setLocation ();
00585   uentry ue = uentry_makeConstant (n, t, loc);
00586   ctype etype = exprNode_getType (expr);
00587 
00588   if (!ctype_isRealInt (etype)) {
00589     voptgenerror 
00590       (FLG_ENUMMEMBERS,
00591        message
00592        ("Value of enum member is not an integeral type (type %s): %s",
00593         ctype_unparse (etype), exprNode_unparse (expr)),
00594        exprNode_loc (expr));
00595   }
00596   
00597   ue->ukind = KENUMCONST;
00598   uentry_setDefined (ue, loc);
00599   return ue;
00600 }
00601 
00602 # ifndef NOLCL
00603 /*@notnull@*/ uentry uentry_makeSpecEnumConstant (cstring n, ctype t, fileloc loc)
00604 {
00605   uentry ue = uentry_makeConstant (n, t, loc);
00606 
00607   ue->ukind = KENUMCONST;
00608   return ue;
00609 }
00610 # endif
00611 
00612 /*@notnull@*/ uentry uentry_makeVariableLoc (cstring n, ctype t)
00613 {
00614   return uentry_makeVariable (n, t, setLocation (), FALSE);
00615 }
00616 
00617 # ifndef NOLCL
00618 /*@notnull@*/ /*@only@*/ uentry uentry_makeUnnamedVariable (ctype t)
00619 {
00620   return uentry_makeVariable (cstring_undefined, t, setLocation (), FALSE);
00621 }
00622 # endif
00623 
00624 /*@notnull@*/ uentry uentry_makeIdDatatype (idDecl id)
00625 {
00626   ctype ct = idDecl_getCtype (id);
00627   uentry ue = uentry_makeDatatype (idDecl_observeId (id), ct, 
00628                                    MAYBE, MAYBE, setLocation ());
00629 
00630   uentry_reflectQualifiers (ue, idDecl_getQuals (id));
00631   
00632   if (!ynm_isOn (ue->info->datatype->abs))
00633     {
00634       if (ctype_isUnknown (ct))
00635         {
00636           ue->info->datatype->mut = MAYBE;
00637         }
00638       else
00639         {
00640           ue->info->datatype->mut = ynm_fromBool (ctype_isMutable (ct));
00641         }
00642     }
00643   
00644   return ue;
00645 }
00646 
00647 void uentry_checkParams (uentry ue)
00648 {
00649   if (uentry_isValid (ue))
00650     {
00651       bool isExt = uentry_isExtern (ue);
00652 
00653       if (uentry_isRealFunction (ue))
00654         {
00655           uentryList params = uentry_getParams (ue);
00656 
00657           uentryList_elements (params, current)
00658             {
00659               if (uentry_isValid (current))
00660                 {
00661                   ctype ct = current->utype;                  
00662                   
00663                   if (ctype_isFixedArray (ct))
00664                     {
00665                       if (ctype_isArray (ctype_baseArrayPtr (ct))
00666                           && !ctype_isFixedArray (ctype_baseArrayPtr (ct)))
00667                         {
00668                           ;
00669                         }
00670                       else
00671                         {
00672                           voptgenerror 
00673                             (FLG_FIXEDFORMALARRAY,
00674                              message ("Function parameter %q declared as "
00675                                       "manifest array (size constant is meaningless)",
00676                                       uentry_getName (current)),
00677                              uentry_whereDeclared (current));
00678                         }
00679                     }
00680                   else 
00681                     {
00682                       if (ctype_isArray (ct))
00683                         {
00684                           voptgenerror 
00685                             (FLG_FORMALARRAY,
00686                              message ("Function parameter %q declared as "
00687                                       "array (treated as pointer)", 
00688                                       uentry_getName (current)),
00689                              uentry_whereDeclared (current));
00690                         }
00691                     }
00692 
00693                   if (sRef_getNullState (uentry_getSref (current)) == NS_MNOTNULL)
00694                     {
00695                       if (ctype_isAbstract (ct) && 
00696                           (isExt || (ctype_isAbstract (ctype_realType (ct))
00697                                      && !context_hasFileAccess (ctype_typeId (ct)))))
00698                         {
00699                           vgenhinterror 
00700                             (FLG_INCONDEFS,
00701                              message 
00702                              ("Function %q declared with notnull parameter %q of abstract "
00703                               "type %s",
00704                               uentry_getName (ue),
00705                               uentry_getName (current),
00706                               ctype_unparse (ct)),
00707                              message 
00708                              ("Since %s is an abstract type, notnull can only be "
00709                               "used for parameters if the function is static to a "
00710                               "module where %s is accessible.",
00711                               ctype_unparse (ct),
00712                               ctype_unparse (ct)),
00713                              uentry_whereDeclared (current));
00714                         }
00715                     }
00716                 }
00717             } end_uentryList_elements;
00718           
00719           if (sRef_getNullState (uentry_getSref (ue)) == NS_MNOTNULL)
00720             {
00721               ctype ct = ue->utype;
00722                   
00723               if (ctype_isAbstract (ct) 
00724                   && (isExt || (ctype_isAbstract (ctype_realType (ct))
00725                                 && !context_hasFileAccess (ctype_typeId (ct)))))
00726                 {
00727                   vgenhinterror 
00728                     (FLG_INCONDEFS,
00729                      message 
00730                      ("%s %q declared %s notnull storage of abstract type %s",
00731                       ekind_capName (uentry_getKind (ue)),
00732                       uentry_getName (ue),
00733                       fcnErrName (ue),
00734                       ctype_unparse (ct)),
00735                      message 
00736                      ("Since %s is an abstract type, notnull can only be used "
00737                       "if it is static to a module where %s is accessible.",
00738                       ctype_unparse (ct),
00739                       ctype_unparse (ct)),
00740                      uentry_whereDeclared (ue));
00741                 }
00742             }
00743         }
00744     }
00745 }
00746 
00747 static void reflectImplicitFunctionQualifiers (/*@notnull@*/ uentry ue, bool spec)
00748 {
00749   alkind ak = sRef_getAliasKind (ue->sref);
00750 
00751   if (alkind_isRefCounted (ak))
00752     {
00753       sRef_setAliasKind (ue->sref, AK_NEWREF, fileloc_undefined);
00754     }
00755   else 
00756     {
00757       if (alkind_isUnknown (ak))
00758         {
00759           exkind ek = sRef_getExKind (ue->sref);
00760           
00761           if (exkind_isKnown (ek))
00762             {
00763               sRef_setAliasKind (ue->sref, AK_IMPDEPENDENT, fileloc_undefined);
00764             }
00765           else 
00766             {
00767               if (context_getFlag (spec ? FLG_SPECRETIMPONLY : FLG_RETIMPONLY))
00768                 {
00769                   if (ctype_isVisiblySharable 
00770                       (ctype_realType (ctype_returnValue (ue->utype))))
00771                     {
00772                       if (uentryList_hasReturned (uentry_getParams (ue)))
00773                         {
00774                           ;
00775                         }
00776                       else
00777                         {
00778                           sRef_setAliasKind (ue->sref, AK_IMPONLY, 
00779                                              fileloc_undefined);
00780                                                 }
00781                     }
00782                 }
00783             }
00784         }
00785     }
00786 }
00787 
00788 static /*@notnull@*/ uentry 
00789 uentry_makeFunctionAux (cstring n, ctype t, 
00790                         typeIdSet access,
00791                         /*@only@*/ globSet globs, 
00792                         /*@only@*/ sRefSet mods, 
00793                         /*@keep@*/ fileloc f, bool priv,
00794                         /*@unused@*/ bool isForward)
00795 {
00796   uentry e = uentry_alloc ();
00797   ctype ret;
00798 
00799   if (ctype_isFunction (t))
00800     {
00801       ret = ctype_returnValue (t);
00802     }
00803   else
00804     {
00805       if (ctype_isKnown (t))
00806         {
00807           llbug (message ("not function: %s", ctype_unparse (t)));
00808         }
00809       ret = ctype_unknown;
00810     }
00811 
00812   e->ukind = KFCN;
00813 
00814   if (fileloc_isSpec (f) || fileloc_isImport (f))
00815     {
00816       e->whereSpecified = f;
00817       e->whereDeclared = fileloc_undefined;
00818     }
00819   else
00820     {
00821       e->whereSpecified = fileloc_undefined;
00822       e->whereDeclared = f;
00823     }
00824 
00825   /* e->shallowCopy = FALSE; */
00826   e->uname = cstring_copy (n);
00827   e->utype = t;
00828   e->storageclass = SCNONE;
00829 
00830     e->sref = sRef_makeType (ret);
00831 
00832   if (ctype_isUA (ret))
00833     {
00834       sRef_setStateFromType (e->sref, ret);
00835     }
00836   
00837   e->used = FALSE;
00838   e->lset = FALSE;
00839   e->uses = filelocList_new ();
00840   e->isPrivate = priv;
00841   e->hasNameError = FALSE;
00842 
00843   e->info = (uinfo) dmalloc (sizeof (*e->info));
00844   e->info->fcn = (ufinfo) dmalloc (sizeof (*e->info->fcn));
00845 
00846   e->info->fcn->hasMods = sRefSet_isDefined (mods);
00847   e->info->fcn->hasGlobs = globSet_isDefined (globs);
00848 
00849   e->info->fcn->exitCode = XK_UNKNOWN;
00850   e->info->fcn->nullPred = QU_UNKNOWN;
00851   e->info->fcn->specialCode = SPC_NONE;
00852 
00853   e->info->fcn->access = access;
00854   e->info->fcn->globs = globs;
00855   e->info->fcn->defparams = uentryList_undefined;
00856 
00857   sRef_setDefined (e->sref, f);
00858   e->whereDefined = fileloc_undefined;
00859   
00860   e->info->fcn->mods = sRefSet_undefined;
00861   e->info->fcn->specclauses = NULL;
00862   checkGlobalsModifies (e, mods);
00863   e->info->fcn->mods = mods;
00864 
00865   return (e);
00866 }
00867 
00868 /*@notnull@*/ uentry uentry_makeIdFunction (idDecl id)
00869 {
00870   uentry ue = 
00871     uentry_makeFunction (idDecl_observeId (id), idDecl_getCtype (id), 
00872                          typeId_invalid, globSet_undefined, 
00873                          sRefSet_undefined, 
00874                          setLocation ());
00875   
00876   uentry_reflectQualifiers (ue, idDecl_getQuals (id));
00877   reflectImplicitFunctionQualifiers (ue, FALSE);
00878 
00879   if (!uentry_isStatic (ue)
00880       && cstring_equalLit (ue->uname, "main"))
00881     {
00882       ctype typ = ue->utype;
00883       ctype retval;
00884       uentryList args;
00885 
00886       llassert (ctype_isFunction (typ));
00887 
00888       retval = ctype_returnValue (typ);
00889 
00890       if (!ctype_isInt (retval))
00891         {
00892           voptgenerror 
00893             (FLG_MAINTYPE,
00894              message ("Function main declared to return %s, should return int",
00895                       ctype_unparse (retval)),
00896              uentry_whereDeclared (ue));
00897         }
00898 
00899       args = ctype_argsFunction (typ);
00900 
00901       if (uentryList_isMissingParams (args) 
00902           || uentryList_size (args) == 0)
00903         {
00904           ;
00905         }
00906       else
00907         {
00908           if (uentryList_size (args) != 2)
00909             {
00910               voptgenerror 
00911                 (FLG_MAINTYPE,
00912                  message ("Function main declared with %d arg%p, "
00913                           "should have 2 (int argc, char *argv[])",
00914                           uentryList_size (args)),
00915                  uentry_whereLast (ue));
00916             }
00917           else
00918             {
00919               uentry arg = uentryList_getN (args, 0);
00920               ctype ct = uentry_getType (arg);
00921 
00922               if (!ctype_isInt (ct))
00923                 {
00924                   voptgenerror 
00925                     (FLG_MAINTYPE,
00926                      message ("Parameter 1, %q, of function main declared "
00927                               "with type %t, should have type int",
00928                               uentry_getName (arg), ct),
00929                      uentry_whereDeclared (arg));
00930                 }
00931 
00932               arg = uentryList_getN (args, 1);
00933               ct = uentry_getType (arg);
00934 
00935               if (ctype_isArrayPtr (ct)
00936                   && ctype_isArrayPtr (ctype_baseArrayPtr (ct))
00937                   && ctype_isChar (ctype_baseArrayPtr (ctype_baseArrayPtr (ct))))
00938                 {
00939                   ;
00940                 }
00941               else
00942                 {
00943                   voptgenerror 
00944                     (FLG_MAINTYPE,
00945                      message ("Parameter 2, %q, of function main declared "
00946                               "with type %t, should have type char **",
00947                               uentry_getName (arg), ct),
00948                      uentry_whereDeclared (arg));
00949                 }
00950             }
00951         }
00952     }
00953 
00954   return ue;
00955 }
00956 
00957 static void uentry_implicitParamAnnots (/*@notnull@*/ uentry e)
00958 {
00959   alkind ak = sRef_getAliasKind (e->sref);
00960 
00961   if ((alkind_isUnknown (ak) || alkind_isImplicit (ak))
00962       && context_getFlag (FLG_PARAMIMPTEMP))
00963     {
00964       exkind ek = sRef_getExKind (e->sref);
00965       
00966       if (exkind_isKnown (ek))
00967         {
00968           sRef_setAliasKind (e->sref, AK_IMPDEPENDENT, fileloc_undefined);
00969           sRef_setOrigAliasKind (e->sref, AK_IMPDEPENDENT);
00970         }
00971       else
00972         {
00973           sRef_setAliasKind (e->sref, AK_IMPTEMP, fileloc_undefined);
00974           sRef_setOrigAliasKind (e->sref, AK_IMPTEMP);
00975         }
00976     }
00977 }
00978 
00979 static /*@only@*/ /*@notnull@*/ uentry 
00980 uentry_makeVariableParamAux (cstring n, ctype t, sRef s, sstate defstate)
00981 {
00982   cstring pname = makeParam (n);
00983   uentry e = uentry_makeVariableAux (pname, t, setLocation (), s, FALSE, VKPARAM);
00984 
00985   cstring_free (pname);
00986   uentry_implicitParamAnnots (e);
00987 
00988   if (!sRef_isAllocated (e->sref) && !sRef_isPartial (e->sref))
00989     {
00990       sRef_setDefState (e->sref, defstate, uentry_whereDeclared (e));
00991       e->info->var->defstate = defstate;
00992     }
00993 
00994   return (e);
00995 }
00996 
00997 # ifndef NOLCL
00998 void
00999 uentry_setRefCounted (uentry e)
01000 {
01001   if (uentry_isValid (e))
01002     {
01003       uentry_setAliasKind (e, AK_REFCOUNTED);
01004       sRef_storeState (e->sref);
01005     }
01006 }
01007 # endif
01008 
01009 void
01010 uentry_setStatic (uentry c)
01011 {
01012   if (uentry_isValid (c)) 
01013     {
01014       alkind ak = sRef_getAliasKind (c->sref);
01015       c->storageclass = SCSTATIC;
01016 
01017       if (uentry_isVariable (c) && !ctype_isFunction (uentry_getType (c)))
01018         {
01019           if (!alkind_isUnknown (ak)
01020               && !alkind_isStatic (ak))
01021             {
01022               if  (!(ctype_isRealPointer (uentry_getType (c)))
01023                    && !(ctype_isAbstract (ctype_realType (uentry_getType (c))))
01024                    && !alkind_isRefCounted (ak))
01025                 {
01026                   if (alkind_isImplicit (ak)
01027                       && alkind_isDependent (ak)
01028                       && ctype_isArray (uentry_getType (c)))
01029                     {
01030                       ; /* no error for observer arrays */
01031                     }
01032                   else
01033                     {
01034                       voptgenerror 
01035                         (FLG_INCONDEFS,
01036                          message ("Static storage %q declared as %s",
01037                                   uentry_getName (c),
01038                                   alkind_unparse (ak)),
01039                          uentry_whereDeclared (c));
01040                     }
01041                 }
01042             }
01043           else
01044             {
01045               if (alkind_isUnknown (ak)
01046                   || (alkind_isImplicit (sRef_getAliasKind (c->sref))
01047                       && !alkind_isDependent (sRef_getAliasKind (c->sref))))
01048                 {
01049                   sRef_setAliasKind (c->sref, AK_STATIC, fileloc_undefined);
01050                   sRef_setOrigAliasKind (c->sref, AK_STATIC);
01051                 }
01052             }
01053         }
01054     }
01055 }
01056 
01057 void
01058 uentry_setExtern (uentry c)
01059 {
01060   if (uentry_isValid (c)) 
01061     c->storageclass = SCEXTERN;
01062 }
01063 
01064 void
01065 uentry_setParamNo (uentry ue, int pno)
01066 {
01067   llassert (uentry_isAnyParam (ue) && sRef_isParam (ue->sref));
01068   sRef_setParamNo (ue->sref, pno);
01069 }
01070 
01071 static
01072 void checkGlobalsModifies (/*@notnull@*/ uentry ue, sRefSet sr)
01073 {
01074   sRefSet_allElements (sr, el)
01075     {
01076       sRef base = sRef_getRootBase (el);
01077       
01078       if (sRef_isGlobal (base) || sRef_isInternalState (base)
01079           || (sRef_isKindSpecial (base) && !sRef_isNothing (base)))
01080         {
01081           if (!globSet_member (ue->info->fcn->globs, base))
01082             {
01083               if (uentry_hasGlobs (ue)
01084                   || context_getFlag (FLG_WARNMISSINGGLOBALSNOGLOBS))
01085                 {
01086                   if (optgenerror 
01087                       (FLG_WARNMISSINGGLOBALS,
01088                        message
01089                        ("Modifies list for %q uses global %q, "
01090                         "not included in globals list.",
01091                         uentry_getName (ue),
01092                         sRef_unparse (base)),
01093                        uentry_whereLast (ue)))
01094                     {
01095                       uentry_showWhereSpecified (ue);
01096                     } 
01097                 }
01098               
01099               ue->info->fcn->globs = globSet_insert (ue->info->fcn->globs, 
01100                                                      base);
01101               if (sRef_isFileStatic (base))
01102                 {
01103                   context_recordFileGlobals (ue->info->fcn->globs);
01104                 }
01105             }
01106         }
01107     } end_sRefSet_allElements;
01108 }
01109 
01110 uentry
01111 uentry_makeVariableSrefParam (cstring n, ctype t, sRef s)
01112 {
01113   return (uentry_makeVariableParamAux (n, t, s, SS_UNKNOWN));
01114 }
01115 
01116 void
01117 uentry_fixupSref (uentry ue)
01118 {
01119   sRef sr;
01120   
01121   if (uentry_isUndefined (ue) || uentry_isElipsisMarker (ue)) 
01122     {
01123       return;
01124     }
01125   
01126   sr = uentry_getSref (ue);
01127 
01128   sRef_resetState (sr);
01129   sRef_clearDerived (sr);
01130   
01131   llassertprint (uentry_isVariable (ue), ("fixing: %s", uentry_unparseFull (ue)));
01132   llassert (sRef_isValid (sr)); 
01133   
01134   if (uentry_isVariable (ue))
01135     {
01136       sRef_setDefState (sr, ue->info->var->defstate, fileloc_undefined);
01137       sRef_setNullState (sr, ue->info->var->nullstate, fileloc_undefined);
01138     }
01139 }
01140 
01141 void uentry_setSpecialClauses (uentry ue, specialClauses clauses)
01142 {
01143   llassert (uentry_isFunction (ue));
01144   llassert (!specialClauses_isDefined (ue->info->fcn->specclauses));
01145 
01146   ue->info->fcn->specclauses = clauses;
01147   specialClauses_checkAll (ue);
01148 }
01149 
01150 /*
01151 ** Used for @modifies@ @endmodifies@ syntax.
01152 **
01153 ** If ue is specified, sr must contain *only*:
01154 **
01155 **      o file static globals
01156 **      o sRef's derived from modifies spec (i.e., more specific than
01157 **        what was specified)
01158 **
01159 ** Otherwise, if sr has modifies it must match sr.
01160 **
01161 ** If it doesn't have modifies, set them to sr.
01162 */
01163 
01164 void
01165 uentry_setModifies (uentry ue, /*@owned@*/ sRefSet sr)
01166 {
01167   if (sRef_modInFunction ())
01168     {
01169       llparseerror
01170         (message ("Modifies list not in function context.  "
01171                   "A modifies list can only appear following the parameter list "
01172                   "in a function declaration or header."));
01173 
01174       /*@-mustfree@*/ return; /*@=mustfree@*/ 
01175     }
01176 
01177   if (sRefSet_hasStatic (sr))
01178     {
01179       context_recordFileModifies (sr);
01180     }
01181 
01182   if (uentry_isValid (ue))
01183     {
01184       if (uentry_isIter (ue))
01185         {
01186           llassert (sRefSet_isUndefined (ue->info->iter->mods));
01187           ue->info->iter->mods = sr;
01188         }
01189       else
01190         {
01191           if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue)))
01192             {
01193               uentry_makeVarFunction (ue);
01194             }
01195           
01196           llassertfatal (uentry_isFunction (ue));
01197           llassert (sRefSet_isUndefined (ue->info->fcn->mods));
01198           
01199           ue->info->fcn->mods = sr;
01200           ue->info->fcn->hasMods = TRUE;
01201           
01202           checkGlobalsModifies (ue, sr);
01203         }
01204       
01205       if (context_getFlag (FLG_MODIFIESIMPNOGLOBALS))
01206         {
01207           ue->info->fcn->hasGlobs = TRUE;
01208         }
01209     }
01210   else
01211     {
01212       sRefSet_free (sr);
01213     }
01214 }
01215 
01216 /*
01217 ** requires: new and old are functions
01218 */
01219  
01220 static void
01221 checkGlobalsConformance (/*@notnull@*/ uentry old, 
01222                          /*@notnull@*/ uentry unew, 
01223                          bool mustConform, bool completeConform)
01224 {
01225   bool hasInternalState = FALSE;
01226 
01227   old->info->fcn->hasGlobs |= unew->info->fcn->hasGlobs;
01228 
01229   if (globSet_isDefined (unew->info->fcn->globs))
01230     {
01231       globSet_allElements (unew->info->fcn->globs, el)
01232         {
01233           if (sRef_isFileStatic (el))
01234             {
01235               sRef sr = globSet_lookup (old->info->fcn->globs, el);
01236 
01237               if (sRef_isInvalid (sr))
01238                 {
01239                   bool hasError = FALSE;
01240 
01241                   if (!hasInternalState 
01242                       && sRef_isInvalid (globSet_lookup (old->info->fcn->globs,
01243                                                          sRef_makeInternalState ()))
01244                       && sRef_isInvalid (globSet_lookup (old->info->fcn->globs,
01245                                                          sRef_makeSpecState ())))
01246                     {
01247                       if (mustConform 
01248                           && !uentry_isStatic (old)
01249                           && optgenerror 
01250                           (FLG_INCONDEFS,
01251                            message ("Globals list for %q includes internal state, %q, "
01252                                     "but %s without globals internalState.",
01253                                     uentry_getName (old),
01254                                     sRef_unparse (el),
01255                                     uentry_specOrDefName (old)),
01256                            uentry_whereLast (unew)))
01257                         {
01258                           uentry_showWhereSpecified (old);
01259                           hasError = TRUE;
01260                         }
01261                       
01262                       old->info->fcn->globs = globSet_insert (old->info->fcn->globs,
01263                                                               sRef_makeInternalState ());
01264                       hasInternalState = TRUE;
01265                     }
01266 
01267                   if (!hasError
01268                       && fileloc_sameFile (uentry_whereDeclared (unew),
01269                                            uentry_whereDeclared (old)))
01270                     {
01271                       if (mustConform
01272                           && optgenerror 
01273                           (FLG_INCONDEFS,
01274                            message ("Function %q inconsistently %rdeclared (in "
01275                                     "same file) with file static global %q in "
01276                                     "globals list",
01277                                     uentry_getName (unew),
01278                                     uentry_isDeclared (old),
01279                                     sRef_unparse (el)),
01280                            uentry_whereDeclared (unew)))
01281                         {
01282                           uentry_showWhereSpecified (old);
01283                         }
01284                     }
01285                 }
01286 
01287               old->info->fcn->globs = globSet_insert (old->info->fcn->globs, el);
01288               context_recordFileGlobals (old->info->fcn->globs);
01289             }
01290           else
01291             {
01292               sRef sr = globSet_lookup (old->info->fcn->globs, el);
01293               
01294               if (sRef_isInvalid (sr))
01295                 {
01296                   if (mustConform
01297                       && optgenerror 
01298                       (FLG_INCONDEFS,
01299                        message ("Function %q inconsistently %rdeclared with "
01300                                 "%q in globals list",
01301                                 uentry_getName (unew),
01302                                 uentry_isDeclared (old),
01303                                 sRef_unparse (el)),
01304                        uentry_whereDeclared (unew)))
01305                     {
01306                       old->info->fcn->globs = globSet_insert (old->info->fcn->globs, el);
01307                       uentry_showWhereSpecified (old);
01308                     }
01309                 }
01310               else
01311                 {
01312                   if (!bool_equal (sRef_isAllocated (el), sRef_isAllocated (sr)))
01313                     {
01314                       if (mustConform
01315                           && optgenerror 
01316                           (FLG_INCONDEFS,
01317                            message 
01318                            ("Function %q global %q inconsistently "
01319                             "%rdeclared as %qout global",
01320                             uentry_getName (unew),
01321                             sRef_unparse (el),
01322                             uentry_isDeclared (old),
01323                             cstring_makeLiteral (sRef_isAllocated (el) ? "" : "non-")),
01324                            uentry_whereDeclared (unew)))
01325                         {
01326                           uentry_showWhereSpecified (old);
01327                         }
01328                     }
01329                 }
01330             }
01331         } end_globSet_allElements ;
01332 
01333       if (completeConform)
01334         {
01335           globSet_allElements (old->info->fcn->globs, el)
01336             {
01337               sRef sr = globSet_lookup (unew->info->fcn->globs, el);
01338               
01339               if (sRef_isInvalid (sr))
01340                 {
01341                   if (mustConform
01342                       && uentry_isReallySpecified (old)
01343                       && optgenerror 
01344                       (FLG_NEEDSPEC,
01345                        message ("Function %q specified with %q in globals list, "
01346                                 "but declared without %q",
01347                                 uentry_getName (unew),
01348                                 sRef_unparse (el),
01349                                 sRef_unparse (el)),
01350                        uentry_whereDeclared (unew)))
01351                     {
01352                       uentry_showWhereSpecified (old);
01353                     }
01354                 }
01355             } end_globSet_allElements;
01356         }
01357     }
01358   else
01359     {
01360       if (completeConform && !globSet_isEmpty (old->info->fcn->globs))
01361         {
01362           if (uentry_isReallySpecified (old)
01363               && optgenerror 
01364               (FLG_NEEDSPEC,
01365                message ("%s %q specified with globals list, but "
01366                         "declared with no globals",
01367                         ekind_capName (unew->ukind),
01368                         uentry_getName (unew)),
01369                uentry_whereDeclared (unew)))
01370             {
01371               llgenindentmsg 
01372                 (message ("Specification globals: %q", 
01373                           globSet_unparse (old->info->fcn->globs)),
01374                  uentry_whereSpecified (old));
01375             }
01376         }
01377       
01378       unew->info->fcn->globs = globSet_copy (unew->info->fcn->globs, 
01379                                             old->info->fcn->globs);
01380     }
01381 }
01382 
01383 /*
01384 ** new modifies list must be included by old modifies list.
01385 **
01386 ** file static state may be added to new, if old has internal.
01387 */
01388 
01389 static void
01390 checkModifiesConformance (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew, 
01391                           bool mustConform, bool completeConform)
01392 {
01393   sRefSet newMods;
01394   bool changedMods = FALSE;
01395   bool modInternal = FALSE;
01396 
01397   llassert (uentry_isFunction (old) && uentry_isFunction (unew));
01398 
01399   old->info->fcn->hasMods |= unew->info->fcn->hasMods;
01400   newMods = unew->info->fcn->mods;
01401             
01402   if (sRefSet_isEmpty (newMods))
01403     {
01404       if (completeConform && !sRefSet_isEmpty (old->info->fcn->mods)
01405           && uentry_isReallySpecified (old))
01406         {
01407           if (optgenerror 
01408               (FLG_NEEDSPEC,
01409                message ("%s %q specified with modifies clause, "
01410                         "but declared with no modifies clause",
01411                         ekind_capName (unew->ukind),
01412                         uentry_getName (unew)),
01413                uentry_whereDeclared (unew)))
01414             {
01415               llgenindentmsg (message ("Specification has modifies %q", 
01416                                        sRefSet_unparse (old->info->fcn->mods)),
01417                               uentry_whereSpecified (old));
01418             }
01419         }
01420 
01421       return;
01422     }
01423 
01424   sRefSet_allElements (newMods, current)
01425     {
01426       if (sRef_isValid (current))
01427         {
01428           sRef rb = sRef_getRootBase (current);
01429           
01430           if (sRef_isFileStatic (rb))
01431             {
01432               if (!modInternal)
01433                 {
01434                   if (!sRefSet_isSameMember (old->info->fcn->mods, 
01435                                              sRef_makeInternalState ())
01436                       && !sRefSet_isSameMember (old->info->fcn->mods, 
01437                                                 sRef_makeSpecState ()))
01438                     {
01439                       if (mustConform 
01440                           && !uentry_isStatic (old)
01441                           && optgenerror 
01442                           (FLG_INCONDEFS,
01443                            message
01444                            ("Modifies list for %q includes internal state, "
01445                             "but %s without modifies internal.",
01446                             uentry_getName (old),
01447                             uentry_specOrDefName (old)),
01448                            uentry_whereLast (unew)))
01449                         {
01450                           uentry_showWhereSpecified (old);
01451                         }
01452                       
01453                       old->info->fcn->mods = 
01454                         sRefSet_insert (old->info->fcn->mods, 
01455                                         sRef_makeInternalState ());
01456                       modInternal = TRUE;
01457                     }
01458                 }
01459               
01460               old->info->fcn->mods = sRefSet_insert (old->info->fcn->mods,
01461                                                      current);
01462               changedMods = TRUE;
01463             }
01464           else
01465             {
01466               if (sRef_canModifyVal (current, old->info->fcn->mods))
01467                 {
01468                   int size = sRefSet_size (old->info->fcn->mods);
01469 
01470                   old->info->fcn->mods = sRefSet_insert (old->info->fcn->mods,
01471                                                          current);
01472 
01473                   if (sRefSet_size (old->info->fcn->mods) != size)
01474                     {
01475                       changedMods = TRUE;
01476                     }
01477                 }
01478               else
01479                 {
01480                   if (mustConform
01481                       && optgenerror 
01482                       (FLG_INCONDEFS,
01483                        message 
01484                        ("Modifies list for %q contains %q, not modifiable "
01485                         "according to %s",
01486                         uentry_getName (old),
01487                         sRef_unparse (current),
01488                         uentry_specDeclName (old)),
01489                        uentry_whereLast (unew)))
01490                     {
01491                       uentry_showWhereSpecified (old);
01492                     }
01493                 }
01494             }
01495         }
01496     } end_sRefSet_allElements;
01497 
01498   if (completeConform && uentry_isReallySpecified (old))
01499     {
01500       sRefSet_allElements (old->info->fcn->mods, el)
01501         {
01502           if (sRef_canModify (el, newMods))
01503             {
01504               ; /* okay */
01505             }
01506           else
01507             {
01508               if (optgenerror 
01509                   (FLG_NEEDSPEC,
01510                    message 
01511                    ("Specification modifies clause for %q contains %q, "
01512                     "not included in declaration modifies clause",
01513                     uentry_getName (old),
01514                     sRef_unparse (el)),
01515                    uentry_whereLast (unew)))
01516                 {
01517                   uentry_showWhereSpecified (old);
01518                 }
01519             }
01520         } end_sRefSet_allElements ;
01521     } 
01522 
01523   /*
01524   ** Make sure file static elements will be removed.
01525   */
01526 
01527   if (changedMods)
01528     {
01529       context_recordFileModifies (old->info->fcn->mods);
01530     }
01531 }
01532 
01533 static void 
01534   uentry_checkMutableType (uentry ue)
01535 {
01536   ctype ct = uentry_getType (ue);
01537 
01538   if (!ctype_isRealPointer (ct) && !ctype_isRealAbstract (ct))
01539     {
01540       voptgenerror (FLG_MUTREP,
01541                     message ("Mutable abstract type %q declared without pointer "
01542                              "indirection: %t (violates assignment semantics)",
01543                              uentry_getName (ue), ct),
01544                     uentry_whereDeclared (ue));
01545     }
01546 }
01547 
01548 void
01549 uentry_setMutable (uentry e)
01550 {
01551   llassert (uentry_isDatatype (e));
01552   e->info->datatype->mut = YES;
01553 }
01554 
01555 static void
01556 uentry_checkIterArgs (uentry ue)
01557 {
01558   bool hasYield = FALSE;
01559   uentryList args;
01560 
01561   llassert (uentry_isIter (ue));
01562 
01563   args = uentry_getParams (ue);
01564 
01565   uentryList_elements (args, el)
01566     {
01567       sstate ds = uentry_getDefState (el);
01568 
01569       if (uentry_isYield (el))
01570         {
01571           hasYield = TRUE;
01572         }
01573 
01574       if (sstate_isUnknown (ds))
01575         {
01576           uentry_setDefState (el, SS_DEFINED);
01577         }
01578       else
01579         {
01580           ;
01581         }
01582     } end_uentryList_elements;
01583 
01584   if (!hasYield)
01585     {
01586       voptgenerror (FLG_HASYIELD,
01587                     message ("Iterator %q declared with no yield parameters",
01588                              uentry_getName (ue)),
01589                     uentry_whereDeclared (ue));
01590     }
01591 }
01592 
01593 static chkind
01594 chkind_fromQual (qual qel)
01595 {
01596   if (qual_isChecked (qel))
01597     {
01598       return CH_CHECKED;
01599     }
01600   else if (qual_isCheckMod (qel))
01601     {
01602       return CH_CHECKMOD;
01603     }
01604   else if (qual_isCheckedStrict (qel))
01605     {
01606       return CH_CHECKEDSTRICT;
01607     }
01608   else if (qual_isUnchecked (qel))
01609     {
01610       return CH_UNCHECKED;
01611     }
01612   else
01613     {
01614       BADEXIT;
01615       /*@notreached@*/ return CH_UNKNOWN;
01616     }
01617 }
01618 
01619 static void
01620 uentry_reflectOtherQualifier (/*@notnull@*/ uentry ue, qual qel)
01621 {
01622   if (qual_isKillRef (qel) || qual_isNewRef (qel) || qual_isTempRef (qel))
01623     {
01624       if (!uentry_isRefCounted (ue))
01625         {
01626           llerror 
01627             (FLG_SYNTAX, 
01628              message ("Reference counting qualifier %s used on non-reference "
01629                       "counted storage: %q",
01630                       qual_unparse (qel), 
01631                       uentry_unparse (ue)));
01632         }
01633       else
01634         {
01635           alkind ak = alkind_fromQual (qel);
01636           
01637           uentry_setAliasKind (ue, ak);
01638         }
01639     }
01640   else if (qual_isRefCounted (qel))
01641     {
01642       ctype ct = ctype_realType (uentry_getType (ue));
01643       ctype rt;
01644       
01645       if (ctype_isPointer (ct) 
01646           && (ctype_isStruct (rt = ctype_realType (ctype_baseArrayPtr (ct)))))
01647         {
01648           /* check there is a refs field */
01649           uentryList fields = ctype_getFields (rt);
01650           uentry refs = uentry_undefined;
01651 
01652           uentryList_elements (fields, field)
01653             {
01654               if (uentry_isRefsField (field))
01655                 {
01656                   if (uentry_isValid (refs))
01657                     {
01658                       llerror 
01659                         (FLG_SYNTAX, 
01660                          message ("Reference counted structure type %s has "
01661                                   "multiple refs fields: %q and %q",
01662                                   ctype_unparse (ct),
01663                                   uentry_getName (refs),
01664                                   uentry_getName (field)));
01665                     }
01666                   
01667                   refs = field;
01668                 }
01669             } end_uentryList_elements;
01670 
01671           if (uentry_isInvalid (refs))
01672             {
01673               vgenhinterror 
01674                 (FLG_SYNTAX, 
01675                  message ("Reference counted structure type %s has "
01676                           "no refs field",
01677                           ctype_unparse (ct)),
01678                  cstring_makeLiteral
01679                  ("To count reference, the structure must have a field named "
01680                   "refs of type int."),
01681                  g_currentloc);           
01682             }
01683           else if (!ctype_isInt (uentry_getType (refs)))
01684             {
01685               llerror 
01686                 (FLG_SYNTAX, 
01687                  message ("Reference counted structure type %s refs field has "
01688                           "type %s (should be int)", ctype_unparse (ct),
01689                           ctype_unparse (uentry_getType (refs))));
01690             }
01691           else
01692             {
01693               sRef_setAliasKind (ue->sref, alkind_fromQual (qel), 
01694                                  uentry_whereDeclared (ue));
01695             }
01696         }
01697       else
01698         {
01699           if ((ctype_isPointer (ct) 
01700                && ctype_isUnknown (ctype_realType (ctype_baseArrayPtr (ct))))
01701               ||ctype_isAbstract (ct) || ctype_isUnknown (ct))
01702             {
01703               sRef_setAliasKind (ue->sref, alkind_fromQual (qel), 
01704                                  uentry_whereDeclared (ue));
01705             }
01706           else
01707             {
01708               llerror 
01709                 (FLG_SYNTAX, 
01710                  message ("Non-pointer to structure type %s declared with "
01711                           "refcounted qualifier",
01712                           ctype_unparse (ct)));
01713             }
01714         }
01715     }
01716   else if (qual_isRefs (qel))
01717     {
01718       if (uentry_isVariable (ue) && !uentry_isParam (ue))
01719         {
01720           uentry_setAliasKind (ue, AK_REFS);
01721         }
01722       else
01723         {
01724           llerror 
01725             (FLG_SYNTAX, 
01726              message ("Refs qualifier used on non-structure field: %q",
01727                       uentry_unparse (ue)));
01728         }
01729     }
01730   else if (qual_isAliasQual (qel))
01731     {
01732       alkind ak = alkind_fromQual (qel);
01733       bool okay = TRUE;
01734       alkind oldak = uentry_getAliasKind (ue);
01735       ctype ut = uentry_getType (ue);
01736       
01737       if (alkind_isImplicit (ak) 
01738           && (alkind_isKnown (oldak) && !alkind_isImplicit (oldak)))
01739         {
01740           /* ignore the implied qualifier */
01741           okay = FALSE;
01742         }
01743       
01744       if (uentry_isEitherConstant (ue))
01745         {
01746           llerror 
01747             (FLG_SYNTAX, 
01748              message ("Alias qualifier %s used on constant: %q",
01749                       alkind_unparse (ak), uentry_unparse (ue)));
01750           okay = FALSE;
01751         }
01752       
01753       if (ctype_isFunction (ut))
01754         {
01755           ut = ctype_returnValue (ut);
01756         }
01757       
01758       if (!(ctype_isVisiblySharable (ut) 
01759             || ctype_isRealArray (ut)
01760             || ctype_isRealSU (ut)))
01761         {
01762           if (!qual_isImplied (qel))
01763             {
01764               llerror 
01765                 (FLG_SYNTAX, 
01766                  message ("Alias qualifier %s used on unsharable storage type %t: %q",
01767                           alkind_unparse (ak), ut, uentry_getName (ue)));
01768             }
01769           
01770           okay = FALSE;
01771         }
01772       else
01773         {
01774           if (uentry_isRefCounted (ue))
01775             {
01776               if (!(qual_isRefQual (qel) || qual_isOnly (qel)
01777                     || qual_isExposed (qel) 
01778                     || qual_isObserver (qel)))
01779                 {
01780                   if (!qual_isImplied (qel))
01781                     {
01782                       llerror 
01783                         (FLG_SYNTAX, 
01784                          message 
01785                          ("Alias qualifier %s used on reference counted storage: %q",
01786                           alkind_unparse (ak), 
01787                           uentry_unparse (ue)));
01788                     }
01789                   
01790                   okay = FALSE;
01791                 }
01792             }
01793           else
01794             {
01795               if (qual_isRefQual (qel))
01796                 {
01797                   llerror 
01798                     (FLG_SYNTAX, 
01799                      message ("Qualifier %s used on non-reference counted storage: %q",
01800                               alkind_unparse (ak), uentry_unparse (ue)));
01801                   
01802                   okay = FALSE;
01803                 }
01804             }
01805         }
01806       
01807       if (okay)
01808         {
01809           uentry_setAliasKind (ue, ak);
01810         }
01811     }
01812   else if (qual_isNull (qel))
01813     {
01814       if (uentry_isConstant (ue))
01815         {
01816           sRef_setNullState 
01817             (ue->sref, 
01818              ctype_isAbstract (ue->utype) ? NS_CONSTNULL : NS_DEFNULL, 
01819              uentry_whereDeclared (ue));
01820         }
01821       else
01822         {
01823           uentry_setNullState (ue, NS_POSNULL);
01824         }
01825     }
01826   else if (qual_isRelNull (qel))
01827     {
01828       uentry_setNullState (ue, NS_RELNULL);
01829     }
01830   else if (qual_isNotNull (qel))
01831     {
01832       uentry_setNullState (ue, NS_MNOTNULL);
01833     }
01834   else if (qual_isAbstract (qel)
01835            || qual_isConcrete (qel))
01836     {
01837       if (!uentry_isDatatype (ue))
01838         {
01839           llerror 
01840             (FLG_SYNTAX, 
01841              message ("Qualifier %s used with non-datatype", 
01842                       qual_unparse (qel)));
01843         }
01844       else
01845         {
01846           ue->info->datatype->abs = ynm_fromBool (qual_isAbstract (qel));
01847         }
01848     }
01849   else if (qual_isMutable (qel))
01850     {
01851       if (!uentry_isDatatype (ue))
01852         {
01853           llerror (FLG_SYNTAX,
01854                    message ("Qualifier %s used with non-datatype", qual_unparse (qel)));
01855         }
01856       else
01857         {
01858           if (!ynm_isOn (ue->info->datatype->mut))
01859             {
01860               uentry_checkMutableType (ue);
01861             }
01862           
01863           ue->info->datatype->mut = YES;
01864         }
01865     }
01866   else if (qual_isImmutable (qel))
01867     {
01868       if (!uentry_isDatatype (ue))
01869         {
01870           llerror (FLG_SYNTAX, message ("Qualifier %s used with non-datatype", 
01871                                         qual_unparse (qel)));
01872         }
01873       else
01874         {
01875           ue->info->datatype->mut = NO;
01876         }
01877     }
01878   else if (qual_isNullPred (qel))
01879     {
01880       if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue)))
01881         {
01882           uentry_makeVarFunction (ue);
01883         }
01884       
01885       if (uentry_isFunction (ue))
01886         {
01887           ctype typ = uentry_getType (ue);
01888           ctype rtype = ctype_returnValue (uentry_getType (ue));
01889           
01890           if (ctype_isRealBool (rtype))
01891             {
01892               uentryList pl = ctype_argsFunction (typ);
01893               
01894               if (uentryList_size (pl) == 1)
01895                 {
01896                   ue->info->fcn->nullPred = qel;
01897                 }
01898               else
01899                 {
01900                   llerror (FLG_SYNTAX, 
01901                            message ("Qualifier %s used with function having %d "
01902                                     "arguments (should have 1)", 
01903                                     qual_unparse (qel),
01904                                     uentryList_size (pl)));
01905                 }
01906             }
01907           else
01908             {
01909               llerror (FLG_SYNTAX, 
01910                        message ("Qualifier %s used with function returning %s "
01911                                 "(should return bool)", 
01912                                 qual_unparse (qel),
01913                                 ctype_unparse (rtype)));
01914             }
01915         }
01916       else
01917         {
01918           llerror (FLG_SYNTAX, 
01919                    message ("Qualifier %s used with non-function", 
01920                             qual_unparse (qel)));
01921         }
01922     }
01923   else if (qual_isExitQual (qel))
01924     {
01925       exitkind exk = exitkind_fromQual (qel);
01926       
01927       if (uentry_isFunction (ue))
01928         {
01929           if (exitkind_isKnown (ue->info->fcn->exitCode))
01930             {
01931               llerror (FLG_SYNTAX, 
01932                        message ("Multiple exit qualifiers used on function %q:  %s, %s", 
01933                                 uentry_getName (ue),
01934                                 exitkind_unparse (ue->info->fcn->exitCode),
01935                                 exitkind_unparse (exk)));
01936             }
01937           
01938           ue->info->fcn->exitCode = exk;
01939         }
01940       else
01941         {
01942           if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue)))
01943             {
01944               uentry_makeVarFunction (ue);
01945               ue->info->fcn->exitCode = exk;
01946             }
01947           else
01948             {
01949               llerror (FLG_SYNTAX,
01950                        message ("Exit qualifier %s used with non-function (type %s)", 
01951                                 qual_unparse (qel),
01952                                 ctype_unparse (uentry_getType (ue))));
01953             }
01954         }
01955     }
01956   else
01957     {
01958       if (qual_isCQual (qel))
01959         {
01960           ; /* okay */
01961         }
01962       else
01963         {
01964           llbug (message ("unhandled qualifier: %s", qual_unparse (qel)));
01965         }
01966     }
01967 }
01968 
01969 void
01970 uentry_reflectQualifiers (uentry ue, qualList q)
01971 {
01972   llassert (uentry_isValid (ue)); 
01973 
01974   qualList_elements (q, qel)
01975     {
01976       if (qual_isStatic (qel))
01977         {
01978           uentry_setStatic (ue);
01979         }
01980       else if (qual_isUnused (qel))
01981         {
01982           uentry_setUsed (ue, fileloc_undefined);         
01983         }
01984       else if (qual_isExternal (qel))
01985         {
01986           fileloc_free (ue->whereDefined);
01987           ue->whereDefined = fileloc_createExternal ();
01988         }
01989       else if (qual_isSef (qel))
01990         {
01991           if (uentry_isVariable (ue))
01992             {
01993               vkind vk = ue->info->var->kind;
01994 
01995               llassert (vk != VKREFPARAM);
01996 
01997               if (vk == VKYIELDPARAM)
01998                 {
01999                   llerror
02000                     (FLG_SYNTAX,
02001                      message ("Qualifier sef cannot be used with %s: %q",
02002                               cstring_makeLiteralTemp (vk == VKYIELDPARAM ? "yield" : "returned"),
02003                               uentry_unparse (ue)));
02004                 }
02005               else if (vk == VKRETPARAM)
02006                 {
02007                   ue->info->var->kind = VKSEFRETPARAM;
02008                 }
02009               else
02010                 {
02011                   ue->info->var->kind = VKSEFPARAM;
02012                 }
02013             }
02014           else
02015             {
02016               llerror 
02017                 (FLG_SYNTAX,
02018                  message ("Qualifier sef is meaningful only on parameters: %q", 
02019                           uentry_unparse (ue)));
02020             }
02021         }
02022       else if (qual_isExtern (qel))
02023         {
02024           ue->storageclass = SCEXTERN;
02025         }
02026       else if (qual_isGlobalQual (qel)) /* undef, killed */
02027         {
02028           if (uentry_isVariable (ue))
02029             {
02030               sstate oldstate = ue->info->var->defstate;
02031               sstate defstate = sstate_fromQual (qel);
02032 
02033 
02034               if ((oldstate == SS_UNDEFGLOB && defstate == SS_KILLED)
02035                   || (oldstate == SS_KILLED && defstate == SS_UNDEFGLOB))
02036                 {
02037                   defstate = SS_UNDEFKILLED;
02038                 }
02039               else 
02040                 {
02041                   ; /* any errors? */
02042                 }
02043 
02044               sRef_setDefState (ue->sref, defstate, fileloc_undefined);
02045               ue->info->var->defstate = defstate;
02046             }
02047           else
02048             {
02049               llerror 
02050                 (FLG_SYNTAX, 
02051                  message ("Qualifier %s used on non-variable: %q",
02052                           qual_unparse (qel), uentry_unparse (ue)));          
02053             }
02054         }
02055       else if (qual_isAllocQual (qel)) /* out, partial, reldef, special, etc. */
02056         {
02057           ctype realType = ctype_realType (ue->utype);
02058           sstate defstate = sstate_fromQual (qel);
02059 
02060           if (ctype_isFunction (realType))
02061             {
02062               realType = ctype_realType (ctype_returnValue (realType));
02063             }
02064 
02065           if (qual_isRelDef (qel))
02066             {
02067               ; /* okay anywhere */
02068             }
02069           else
02070             {
02071               if (!ctype_isAP (realType) 
02072                   && !ctype_isSU (realType)
02073                   && !ctype_isUnknown (realType)
02074                   && !ctype_isAbstract (ue->utype))
02075                 {
02076                   llerror 
02077                     (FLG_SYNTAX, 
02078                      message ("Qualifier %s used on non-pointer or struct: %q",
02079                               qual_unparse (qel), uentry_unparse (ue)));
02080                 }
02081             }
02082 
02083           uentry_setDefState (ue, defstate);
02084 
02085           if (sRef_isStateSpecial (ue->sref)
02086               && alkind_isImplicit (sRef_getAliasKind (ue->sref)))
02087             {
02088               sRef_setAliasKind (ue->sref, AK_ERROR, fileloc_undefined);
02089             }
02090         }
02091       else if (qual_isYield (qel))
02092         {
02093           if (uentry_isVariable (ue))
02094             {
02095               ue->info->var->kind = VKYIELDPARAM;
02096             }
02097           else
02098             {
02099               llerror 
02100                 (FLG_SYNTAX, 
02101                  message ("Qualifier %s used on non-iterator parameter: %q",
02102                           qual_unparse (qel), uentry_unparse (ue)));          
02103             }
02104         }
02105       else if (qual_isExQual (qel))
02106         {
02107           exkind ek = exkind_fromQual (qel);
02108           ctype ut = uentry_getType (ue);
02109 
02110           if (ctype_isFunction (ut))
02111             {
02112               ut = ctype_returnValue (ut);
02113             }
02114           
02115           if (!(ctype_isVisiblySharable (ut))
02116               && !(ctype_isArray (ut)) /* can apply to arrays also! */
02117               && !(ctype_isStruct (ctype_realType (ut)))) /* applies to structure fields! */
02118             {
02119               if (!qual_isImplied (qel))
02120                 {
02121                   llerror 
02122                     (FLG_SYNTAX, 
02123                      message ("Qualifier %s used on unsharable storage type %t: %q",
02124                               exkind_unparse (ek), ut, uentry_getName (ue)));
02125                 }
02126             }
02127           else
02128             {
02129               alkind ak = sRef_getAliasKind (ue->sref);
02130 
02131               sRef_setExKind (ue->sref, ek, uentry_whereDeclared (ue));
02132 
02133               if (alkind_isUnknown (ak) || alkind_isImplicit (ak) || alkind_isStatic (ak))
02134                 {
02135                   if (!alkind_isTemp (ak))
02136                     {
02137                       uentry_setAliasKind (ue, AK_IMPDEPENDENT);
02138                     }
02139                 }
02140               else if (alkind_isDependent (ak) || alkind_isTemp (ak)
02141                        || alkind_isOwned (ak))
02142                 {
02143                   ; /* okay */
02144                 }
02145               else
02146                 {
02147                   llerror 
02148                     (FLG_SYNTAX, 
02149                      message ("Exposure qualifier %s used on %s storage (should "
02150                               "be dependent): %q",
02151                               qual_unparse (qel), 
02152                               alkind_unparse (ak),
02153                               uentry_unparse (ue)));
02154                 }
02155             }
02156         }
02157       else if (qual_isGlobCheck (qel))
02158         {
02159           if (uentry_isVariable (ue))
02160             {
02161               chkind ch = chkind_fromQual (qel);                
02162                        
02163               if (ue->info->var->checked != CH_UNKNOWN)
02164                 {
02165                   if (ch == ue->info->var->checked)
02166                     {
02167                       llerror (FLG_SYNTAX, 
02168                                message ("Redundant %s qualifier on %q",
02169                                         qual_unparse (qel),
02170                                         uentry_getName (ue)));
02171                     }
02172                   else
02173                     {
02174                       llerror (FLG_SYNTAX, 
02175                                message
02176                                ("Contradictory %s and %s qualifiers on %q",
02177                                 qual_unparse (qel),
02178                                 checkedName (ue->info->var->checked),
02179                                 uentry_getName (ue)));
02180                     }
02181                 }
02182 
02183               ue->info->var->checked = ch;
02184             }
02185           else
02186             {
02187               llerror
02188                 (FLG_SYNTAX, 
02189                  message ("Qualifier %s used with non-variable", 
02190                           qual_unparse (qel)));
02191             }
02192         }
02193       else if (qual_isReturned (qel))
02194         {
02195           if (uentry_isVariable (ue))
02196             {
02197               ue->info->var->kind = VKRETPARAM;
02198             }
02199           else
02200             {
02201               llerror (FLG_SYNTAX, message ("Qualifier %s used with non-variable", 
02202                                             qual_unparse (qel)));
02203             }
02204         }
02205       else
02206         {
02207           uentry_reflectOtherQualifier (ue, qel);
02208         }
02209 
02210       sRef_storeState (ue->sref);
02211     } end_qualList_elements;
02212 
02213   qualList_clear (q);
02214 }
02215         
02216 bool
02217 uentry_isOnly (uentry ue)
02218 {
02219   return (!uentry_isUndefined (ue) 
02220           && uentry_isVariable (ue) 
02221           && alkind_isOnly (sRef_getOrigAliasKind (ue->sref)));
02222 }
02223 
02224 static void
02225 uentry_setAliasKind (/*@notnull@*/ uentry ue, alkind ak)
02226 {
02227   sRef_setAliasKind (ue->sref, ak, uentry_whereDeclared (ue));
02228   sRef_setOrigAliasKind (ue->sref, ak);
02229 }
02230 
02231 static void
02232 uentry_setNullState (/*@notnull@*/ uentry ue, nstate ns)
02233 {
02234   if (uentry_isVariable (ue))
02235     {
02236       ue->info->var->nullstate = ns;
02237     }
02238 
02239   sRef_setNullState (ue->sref, ns, uentry_whereDeclared (ue));
02240 }
02241 
02242 bool
02243 uentry_isUnique (uentry ue)
02244 {
02245   return (!uentry_isUndefined (ue) 
02246           && uentry_isVariable (ue) 
02247           && alkind_isUnique (sRef_getOrigAliasKind (ue->sref)));
02248 }
02249 
02250 bool
02251 uentry_isFileStatic (uentry ue)
02252 {
02253   return (uentry_isStatic (ue) 
02254           && (!uentry_isVariable (ue)
02255               || sRef_isFileStatic (uentry_getSref (ue))));
02256 }
02257 
02258 bool
02259 uentry_isExported (uentry ue)
02260 {
02261   if (uentry_isValid (ue))
02262     {
02263       if (uentry_isVariable (ue))
02264         {
02265           return (sRef_isRealGlobal (uentry_getSref (ue)));
02266         }
02267       else
02268         {
02269           return !uentry_isStatic (ue);
02270         }
02271     }
02272 
02273   return FALSE;
02274 }
02275 
02276 bool
02277 uentry_isNonLocal (uentry ue)
02278 {
02279   return (uentry_isValid (ue) && uentry_isVariable (ue)
02280           && (sRef_isGlobal (ue->sref) || uentry_isStatic (ue)));
02281 }
02282 
02283 bool
02284 uentry_isGlobal (uentry ue)
02285 {
02286   return (uentry_isValid (ue) && uentry_isVariable (ue) && 
02287           sRef_isGlobal (ue->sref));
02288 }
02289 
02290 bool
02291 uentry_isPrintfLike (uentry ue)
02292 {
02293   return (uentry_isFunction (ue) 
02294           && (ue->info->fcn->specialCode == SPC_PRINTFLIKE));
02295 }
02296 
02297 bool
02298 uentry_isScanfLike (uentry ue)
02299 {
02300   return (uentry_isFunction (ue) 
02301           && (ue->info->fcn->specialCode == SPC_SCANFLIKE));
02302 }
02303 
02304 bool
02305 uentry_isMessageLike (uentry ue)
02306 {
02307   return (uentry_isFunction (ue) 
02308           && (ue->info->fcn->specialCode == SPC_MESSAGELIKE));
02309 }
02310 
02311 static void checkSpecialFunction (/*@notnull@*/ uentry ue)
02312 {
02313   uentryList args = uentry_getParams (ue);
02314 
02315   if (!uentryList_isMissingParams (args))
02316     {
02317       uentry last = uentry_undefined;
02318 
02319       uentryList_elements (args, current)
02320         {
02321           if (uentry_isElipsisMarker (current))
02322             {
02323               if (uentry_isUndefined (last))
02324                 {
02325                   voptgenerror 
02326                     (FLG_SYNTAX,
02327                      message ("Function %q is marked %s, but has no format "
02328                               "string argument before elipsis",
02329                               uentry_getName (ue),
02330                               specCode_unparse (ue->info->fcn->specialCode)),
02331                      uentry_whereLast (ue));
02332                   ue->info->fcn->specialCode = SPC_NONE;
02333                 }
02334               else
02335                 {
02336                   ctype rt = ctype_realType (uentry_getType (last));
02337 
02338                   if (!ctype_match (rt, ctype_string))
02339                     {
02340                       bool okay = FALSE;
02341 
02342                       /* wchar_t * is okay too */
02343                       if (ctype_isAP (rt))
02344                         {
02345                           ctype base = ctype_baseArrayPtr (rt);
02346                           
02347                           if (ctype_isArbitraryIntegral (base)) 
02348                             {
02349                               okay = TRUE;
02350                             }
02351                         }
02352                       
02353                       if (!okay) 
02354                         {
02355                           voptgenerror
02356                             (FLG_SYNTAX,
02357                              message ("Function %q is marked %s, but the argument "
02358                                       "before the elipsis has type %s (should be char *)",
02359                                       uentry_getName (ue),
02360                                       specCode_unparse (ue->info->fcn->specialCode),
02361                                       ctype_unparse (uentry_getType (last))),
02362                              uentry_whereLast (ue));
02363                           
02364                           ue->info->fcn->specialCode = SPC_NONE;
02365                         }
02366                     }
02367                 }
02368               return;
02369             }
02370           last = current;
02371         } end_uentryList_elements ;
02372 
02373       voptgenerror 
02374         (FLG_SYNTAX,
02375          message ("Function %q is marked %s, but has no elipsis parameter",
02376                   uentry_getName (ue),
02377                   specCode_unparse (ue->info->fcn->specialCode)),
02378          uentry_whereLast (ue));
02379 
02380       ue->info->fcn->specialCode = SPC_NONE;
02381     }
02382 }
02383 
02384 void
02385 uentry_setPrintfLike (uentry ue)
02386 {
02387   if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue)))
02388     {
02389       uentry_makeVarFunction (ue);
02390     }
02391   
02392   llassertfatal (uentry_isFunction (ue));
02393   ue->info->fcn->specialCode = SPC_PRINTFLIKE;
02394   checkSpecialFunction (ue);
02395 }
02396 
02397 void
02398 uentry_setScanfLike (uentry ue)
02399 {
02400   if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue)))
02401     {
02402       uentry_makeVarFunction (ue);
02403     }
02404   
02405   llassertfatal (uentry_isFunction (ue));
02406   ue->info->fcn->specialCode = SPC_SCANFLIKE;
02407   checkSpecialFunction (ue);
02408 }
02409 
02410 void
02411 uentry_setMessageLike (uentry ue)
02412 {
02413   if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue)))
02414     {
02415       uentry_makeVarFunction (ue);
02416     }
02417   
02418   llassertfatal (uentry_isFunction (ue));
02419   ue->info->fcn->specialCode = SPC_MESSAGELIKE;
02420   checkSpecialFunction (ue);
02421 }
02422 
02423 bool
02424 uentry_isSpecialFunction (uentry ue)
02425 {
02426   return (uentry_isFunction (ue) 
02427           && (ue->info->fcn->specialCode != SPC_NONE));
02428 }
02429 
02430 /*@notnull@*/ uentry uentry_makeParam (idDecl t, int i)
02431 {
02432   ctype ct = idDecl_getCtype (t);
02433   ctype base = ct;
02434   sRef pref = sRef_makeParam (i, ct);
02435   uentry ue = uentry_makeVariableSrefParam (idDecl_observeId (t), ct, pref);
02436 
02437   uentry_reflectQualifiers (ue, idDecl_getQuals (t));
02438   uentry_implicitParamAnnots (ue);
02439 
02440   /* Parameter type [][] or [x][] is invalid */
02441 
02442   while (ctype_isFixedArray (base)) {
02443     base = ctype_baseArrayPtr (base);
02444   }
02445   
02446   if (ctype_isIncompleteArray (base)) {
02447     base = ctype_baseArrayPtr (base);
02448 
02449     if (ctype_isArray (base)) {
02450       if (!uentry_hasName (ue)) {
02451         (void) optgenerror (FLG_INCOMPLETETYPE, 
02452                             message ("Unnamed function parameter %d is incomplete type (inner array must have bounds): %s",
02453                                      i + 1,
02454                                      ctype_unparse (ct)),
02455                             uentry_whereLast (ue));
02456       } else {
02457         (void) optgenerror (FLG_INCOMPLETETYPE, 
02458                             message ("Function parameter %q is incomplete type (inner array must have bounds): %s",
02459                                      uentry_getName (ue),
02460                                      ctype_unparse (ct)),
02461                             uentry_whereLast (ue));
02462       }
02463     }
02464   }
02465 
02466   return ue;
02467 }
02468 
02469 /*@only@*/ /*@notnull@*/ uentry uentry_makeIdVariable (idDecl t)
02470 {
02471   ctype ct = idDecl_getCtype (t);
02472 
02473   if (ctype_isFunction (ct))
02474     {
02475             return (uentry_makeIdFunction (t));
02476     }
02477   else
02478     {
02479       fileloc loc = setLocation ();
02480       uentry ue = uentry_makeVariable (idDecl_observeId (t), ct, loc, FALSE);
02481       
02482       uentry_reflectQualifiers (ue, idDecl_getQuals (t));
02483 
02484       if (!uentry_isExtern (ue))
02485         {
02486           uentry_setDefined (ue, loc);
02487         }
02488 
02489       return ue;
02490     }
02491 }
02492 
02493 # ifndef NOLCL
02494 /*@notnull@*/ uentry uentry_makeVariableParam (cstring n, ctype t)
02495 {
02496   return (uentry_makeVariableParamAux (n, t, sRef_makeType (t), SS_DEFINED));
02497 }
02498 # endif
02499 
02500 /*
02501 ** constants
02502 */
02503 
02504 /*@only@*/ /*@notnull@*/ 
02505 uentry uentry_makeConstantAux (cstring n, ctype t, 
02506                                /*@keep@*/ fileloc f, bool priv,
02507                                /*@only@*/ multiVal m)
02508 {
02509   uentry e = uentry_alloc ();
02510 
02511   e->ukind = KCONST;
02512   e->uname = cstring_copy (n);
02513   e->utype = t;
02514   e->storageclass = SCNONE;
02515 
02516   e->sref  = sRef_makeConst (t);
02517 
02518   e->lset = FALSE;
02519   e->used = FALSE;
02520   
02521   e->uses = filelocList_new ();
02522   e->isPrivate = priv;
02523   e->hasNameError = FALSE;
02524 
02525   e->info = (uinfo) dmalloc (sizeof (*e->info));
02526   e->info->uconst = (ucinfo) dmalloc (sizeof (*e->info->uconst));
02527   e->info->uconst->val = m;
02528   e->info->uconst->access = typeIdSet_undefined;
02529 
02530   uentry_setSpecDef (e, f);
02531 
02532   if (multiVal_isInt (m) && (multiVal_forceInt (m) == 0))
02533     {
02534       sRef_setDefNull (e->sref, uentry_whereDeclared (e)); 
02535     }
02536 
02537   return (e);
02538 }
02539 
02540 /*@notnull@*/ uentry uentry_makeConstant (cstring n, ctype t, fileloc f)
02541 {
02542   return (uentry_makeConstantAux (n, t, f, FALSE, multiVal_unknown ()));
02543 }
02544 
02545 /*@notnull@*/ uentry uentry_makeIdConstant (idDecl t)
02546 {
02547   uentry ue = uentry_makeConstant (idDecl_observeId (t), 
02548                                    idDecl_getCtype (t), 
02549                                    fileloc_undefined);
02550 
02551   llassert (fileloc_isUndefined (ue->whereDeclared));
02552   ue->whereDeclared = setLocation ();
02553 
02554   uentry_reflectQualifiers (ue, idDecl_getQuals (t));
02555 
02556   return ue;
02557 }
02558 
02559 /*
02560 ** variables
02561 */
02562 
02563 void uentry_setDefState (uentry ue, sstate defstate)
02564 {
02565   if (uentry_isValid (ue))
02566     {
02567       sRef_setDefState (ue->sref, defstate, fileloc_undefined);
02568 
02569       if (uentry_isVariable (ue))
02570         {
02571           ue->info->var->defstate = defstate; /* evs 2000-05-17: fixed bug, was SS_DEFINED! */
02572         }
02573     }
02574 }
02575 
02576 bool uentry_isCheckedUnknown (uentry ue)
02577 {
02578   return (uentry_isVar (ue) 
02579           && (ue->info->var->checked == CH_UNKNOWN));
02580 }
02581 
02582 bool uentry_isCheckMod (uentry ue)
02583 {
02584   return (uentry_isVar (ue) 
02585           && (ue->info->var->checked == CH_CHECKMOD));
02586 }
02587 
02588 bool uentry_isUnchecked (uentry ue)
02589 {
02590   return (uentry_isVar (ue) 
02591           && (ue->info->var->checked == CH_UNCHECKED));
02592 }
02593 
02594 bool uentry_isChecked (uentry ue)
02595 {
02596   return (uentry_isVar (ue) 
02597           && (ue->info->var->checked == CH_CHECKED));
02598 }
02599 
02600 bool uentry_isCheckedModify (uentry ue)
02601 {
02602   return (uentry_isVar (ue) 
02603           && (ue->info->var->checked == CH_CHECKED
02604               || ue->info->var->checked == CH_CHECKMOD
02605               || ue->info->var->checked == CH_CHECKEDSTRICT));
02606 }
02607 
02608 bool uentry_isCheckedStrict (uentry ue)
02609 {
02610   return (uentry_isVar (ue) 
02611           && (ue->info->var->checked == CH_CHECKEDSTRICT));
02612 }
02613 
02614 void uentry_setUnchecked (uentry ue)
02615 {
02616   llassert (uentry_isVar (ue));
02617 
02618   ue->info->var->checked = CH_UNCHECKED;
02619 }
02620 
02621 void uentry_setChecked (uentry ue)
02622 {
02623   llassert (uentry_isVar (ue));
02624 
02625   ue->info->var->checked = CH_CHECKED;
02626 }
02627 
02628 void uentry_setCheckMod (uentry ue)
02629 {
02630   llassert (uentry_isVar (ue));
02631 
02632   ue->info->var->checked = CH_CHECKMOD;
02633 }
02634 
02635 void uentry_setCheckedStrict (uentry ue)
02636 {
02637   llassert (uentry_isVar (ue));
02638   
02639   ue->info->var->checked = CH_CHECKEDSTRICT;
02640 }
02641 
02642 static /*@only@*/ /*@notnull@*/ 
02643   uentry uentry_makeVariableAux (cstring n, ctype t, 
02644                                  fileloc f,
02645                                  /*@exposed@*/ sRef s,
02646                                  bool priv, vkind kind)
02647 {
02648   uentry e = uentry_alloc ();
02649   ctype rt = t;
02650 
02651   DPRINTF (("Make variable: %s %s %s", n, ctype_unparse (t), sRef_unparse (s)));
02652 
02653   e->ukind = KVAR;
02654   e->uname = cstring_copy (n);
02655   e->utype = t;
02656 
02657   e->storageclass = SCNONE;
02658 
02659   e->sref  = s;
02660 
02661   e->used = FALSE;
02662   e->lset = FALSE;
02663 
02664   e->uses = filelocList_new ();
02665   e->isPrivate = priv;
02666   e->hasNameError = FALSE;
02667 
02668   e->info = (uinfo) dmalloc (sizeof (*e->info));
02669   e->info->var = (uvinfo) dmalloc (sizeof (*e->info->var));
02670   e->info->var->kind = kind;
02671 
02672   e->info->var->checked = CH_UNKNOWN;
02673 
02674   uentry_setSpecDef (e, f);
02675 
02676   if (ctype_isFunction (rt))
02677     {
02678       rt = ctype_returnValue (rt);
02679     }
02680 
02681   if (ctype_isUA (rt))
02682     {
02683       sRef_setStateFromType (e->sref, rt);
02684     }
02685 
02686   e->info->var->defstate = sRef_getDefState (e->sref);  
02687   e->info->var->nullstate = sRef_getNullState (e->sref);
02688 
02689   return (e);
02690 }
02691 
02692 bool
02693 uentry_isYield (uentry ue)
02694 {
02695   return (uentry_isVariable (ue) 
02696           && (ue->info->var->kind == VKYIELDPARAM
02697               || ue->info->var->kind == VKREFYIELDPARAM));
02698 }
02699 
02700 static bool
02701 uentry_isRefsField (uentry ue)
02702 {
02703   return (uentry_isVariable (ue) && sRef_isRefsField (ue->sref));
02704 }
02705 
02706 /*@only@*/ /*@notnull@*/ 
02707 uentry uentry_makeVariable (cstring n, ctype t, fileloc f, bool isPriv)
02708 {
02709   return (uentry_makeVariableAux (n, t, f, sRef_makeType (t), isPriv, 
02710                                   fileloc_isSpec (f) ? VKSPEC : VKNORMAL));
02711 }
02712 
02713 /*
02714 ** functions
02715 */
02716 
02717 void uentry_makeVarFunction (uentry ue)
02718 {
02719   alkind ak;
02720   exkind ek;
02721   uvinfo oldInfo;
02722   fileloc loc;
02723 
02724   llassert (uentry_isValid (ue));
02725   llassert (!sRef_modInFunction ());
02726 
02727   ak = sRef_getOrigAliasKind (ue->sref);
02728   ek = sRef_getOrigExKind (ue->sref);
02729 
02730   oldInfo = ue->info->var;
02731 
02732   llassert (ctype_isUnknown (ue->utype) || ctype_isFunction (ue->utype));
02733 
02734   /*
02735   ** expanded macro is marked used (until I write a pre-processor)
02736   */
02737 
02738   ue->used |= (oldInfo->kind == VKEXPMACRO);
02739 
02740   ue->ukind = KFCN;
02741   ue->info->fcn = (ufinfo) dmalloc (sizeof (*ue->info->fcn));
02742   ue->info->fcn->exitCode = XK_UNKNOWN;
02743   ue->info->fcn->nullPred = QU_UNKNOWN;
02744   ue->info->fcn->specialCode = SPC_NONE;
02745   ue->info->fcn->access = typeIdSet_undefined;
02746   ue->info->fcn->hasGlobs = FALSE;
02747   ue->info->fcn->globs = globSet_undefined;
02748   ue->info->fcn->hasMods = FALSE;
02749   ue->info->fcn->mods = sRefSet_undefined;
02750   ue->info->fcn->specclauses = NULL;
02751   ue->info->fcn->defparams = uentryList_undefined;
02752 
02753   if (ctype_isFunction (ue->utype))
02754     {
02755       ue->sref = sRef_makeType (ctype_returnValue (ue->utype)); 
02756     }
02757   else
02758     {
02759       ue->sref = sRef_makeType (ctype_unknown); 
02760     }
02761 
02762   if (sRef_isRefCounted (ue->sref))
02763     {
02764       ak = AK_NEWREF;
02765     }
02766   else
02767     {
02768       if (alkind_isUnknown (ak))
02769         {
02770           if (exkind_isKnown (ek))
02771             {
02772               ak = AK_IMPDEPENDENT;
02773             }
02774           else 
02775             {
02776               if (context_getFlag (FLG_RETIMPONLY))
02777                 {
02778                   if (ctype_isFunction (ue->utype)
02779                       && ctype_isVisiblySharable 
02780                       (ctype_realType (ctype_returnValue (ue->utype))))
02781                     {
02782                       if (uentryList_hasReturned (uentry_getParams (ue)))
02783                         {
02784                           ;
02785                         }
02786                       else
02787                         {
02788                           ak = AK_IMPONLY;
02789                                                 }
02790                     }
02791                 }
02792             }
02793         }
02794     }
02795 
02796   loc = ue->whereDeclared;
02797 
02798   sRef_setAliasKind (ue->sref, ak, loc);
02799   sRef_setNullState (ue->sref, oldInfo->nullstate, loc);
02800   sRef_setDefState (ue->sref, oldInfo->defstate, loc);
02801   sRef_setExKind (ue->sref, ek, loc);
02802 
02803   if (oldInfo->kind == VKEXPMACRO)
02804     {
02805       fileloc_free (loc);
02806       ue->whereDeclared = fileloc_undefined;
02807     }
02808   else
02809     {
02810       fileloc_free (ue->whereDefined);
02811       ue->whereDefined = fileloc_undefined;
02812     }
02813 
02814   uvinfo_free (oldInfo);
02815 }
02816 
02817 void
02818 uentry_setGlobals (uentry ue, /*@owned@*/ globSet globs)
02819 {
02820   llassert (uentry_isValid (ue));
02821 
02822   if (uentry_isIter (ue))
02823     {
02824       llassert (globSet_isUndefined (ue->info->iter->globs));
02825       ue->info->iter->globs = globs;
02826     }
02827   else
02828     {
02829       if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue)))
02830         {
02831           uentry_makeVarFunction (ue);
02832         }
02833       
02834       llassert (uentry_isFunction (ue));
02835       llassert (!ue->info->fcn->hasGlobs 
02836                 && globSet_isUndefined (ue->info->fcn->globs));
02837       
02838       ue->info->fcn->hasGlobs = TRUE;
02839       /*@-mustfree@*/ ue->info->fcn->globs = globs;
02840       /*@=mustfree@*/
02841     }
02842 
02843   if (globSet_hasStatic (globs))
02844     {
02845       context_recordFileGlobals (globs);
02846     }
02847 
02848   if (context_getFlag (FLG_GLOBALSIMPMODIFIESNOTHING))
02849     {
02850       ue->info->fcn->hasMods = TRUE;
02851     }
02852 }
02853 
02854 void uentry_addAccessType (uentry ue, typeId tid)
02855 {
02856   if (uentry_isFunction (ue))
02857     {
02858       ue->info->fcn->access = typeIdSet_insert (ue->info->fcn->access, tid);
02859     }
02860   else if (uentry_isEitherConstant (ue))
02861     {
02862       ue->info->uconst->access = typeIdSet_insert (ue->info->uconst->access, tid);
02863     }
02864   else if (uentry_isIter (ue))
02865     {
02866       ue->info->iter->access = typeIdSet_insert (ue->info->iter->access, tid);
02867     }
02868   else if (uentry_isEndIter (ue))
02869     {
02870       ue->info->enditer->access = typeIdSet_insert (ue->info->enditer->access, tid);
02871     }
02872   else
02873     {
02874       llbug (message ("no access for: %q", uentry_unparse (ue)));
02875     }
02876 }
02877 
02878 /*@only@*/ /*@notnull@*/ uentry 
02879   uentry_makeFunction (cstring n, ctype t, 
02880                        typeId access, 
02881                        /*@only@*/ globSet globs, /*@only@*/ sRefSet mods, 
02882                        fileloc f)
02883 {
02884   return (uentry_makeFunctionAux (n, t, 
02885                                   ((typeId_isInvalid (access)) ? typeIdSet_emptySet () 
02886                                    : typeIdSet_single (access)),
02887                                   globs, mods, f,
02888                                   FALSE, FALSE));
02889 }
02890 
02891 # ifndef NOLCL
02892 /*@notnull@*/ uentry 
02893   uentry_makePrivFunction2 (cstring n, ctype t, 
02894                             typeIdSet access, 
02895                             globSet globs, sRefSet mods, 
02896                             fileloc f)
02897 {
02898   return (uentry_makeFunctionAux (n, t, access, globs, mods, f, TRUE, FALSE));
02899 }
02900 
02901 
02902 /*@notnull@*/ uentry 
02903   uentry_makeSpecFunction (cstring n, ctype t, 
02904                            typeIdSet access,
02905                            /*@only@*/ globSet globs, 
02906                            /*@only@*/ sRefSet mods, 
02907                            fileloc f)
02908 {
02909   uentry ue = uentry_makeFunctionAux (n, t, access, 
02910                                       globs, mods, f,
02911                                       FALSE, FALSE);
02912 
02913   uentry_setHasGlobs (ue);
02914   uentry_setHasMods (ue);
02915 
02916   reflectImplicitFunctionQualifiers (ue, TRUE);
02917   return (ue);
02918 }
02919 # endif
02920 
02921 uentry uentry_makeExpandedMacro (cstring s, fileloc f)
02922 {
02923   uentry ue = uentry_makeVariableAux (s, ctype_unknown, fileloc_undefined, 
02924                                       sRef_undefined, FALSE, VKEXPMACRO);
02925 
02926   uentry_setDefined (ue, f);
02927   return ue;
02928 }
02929 
02930 /*@notnull@*/ /*@notnull@*/ uentry 
02931   uentry_makeForwardFunction (cstring n, typeId access, fileloc f)
02932 {
02933   uentry ue = uentry_makeFunctionAux (n, ctype_unknown, 
02934                                       typeIdSet_singleOpt (access),
02935                                       globSet_undefined, sRefSet_undefined, 
02936                                       fileloc_undefined,
02937                                       FALSE, TRUE);
02938 
02939   ue->whereDeclared = fileloc_update (ue->whereDeclared, f);
02940   return ue;
02941 }
02942 
02943 bool uentry_isForward (uentry e)
02944 {
02945   if (uentry_isValid (e))
02946     {
02947       ctype ct = uentry_getType (e);
02948 
02949       return (ctype_isUnknown (ct)
02950               || (ctype_isFunction (ct)
02951                   && ctype_isUnknown (ctype_returnValue (ct))));
02952     }
02953 
02954   return FALSE;
02955 }
02956 
02957 # ifndef NOLCL
02958 /*@notnull@*/ uentry 
02959 uentry_makeTypeListFunction (cstring n, typeIdSet access, fileloc f)
02960 {
02961   return (uentry_makeFunctionAux (n, ctype_unknown, access,
02962                                   globSet_new (),
02963                                   sRefSet_new (), f,
02964                                   FALSE, TRUE));
02965 }
02966 
02967 /*@notnull@*/ uentry 
02968 uentry_makeUnspecFunction (cstring n, ctype t, 
02969                            typeIdSet access, 
02970                            fileloc f)
02971 {
02972   uentry ue = uentry_makeFunctionAux (n, t, access, globSet_new (),
02973                                       sRefSet_new (), f, FALSE, TRUE);
02974 
02975   reflectImplicitFunctionQualifiers (ue, TRUE);
02976   return ue;
02977 }
02978 # endif
02979 
02980 /*
02981 ** datatypes
02982 */
02983 
02984 /* is exported for use by usymtab_interface */
02985 
02986 /*@notnull@*/ uentry 
02987   uentry_makeDatatypeAux (cstring n, ctype t, ynm mut, ynm abs, 
02988                           fileloc f, bool priv)
02989 {
02990   uentry e = uentry_alloc ();
02991 
02992   /* e->shallowCopy = FALSE; */
02993   e->ukind = KDATATYPE;
02994   e->uname = cstring_copy (n);
02995   e->utype = t;
02996   e->storageclass = SCNONE;
02997   e->sref  = sRef_makeUnknown ();
02998 
02999   if (ctype_isUA (t))
03000     {
03001       sRef_setStateFromType (e->sref, t);
03002     }
03003 
03004   uentry_setSpecDef (e, f);
03005 
03006   e->uses = filelocList_new ();
03007   e->isPrivate = priv;
03008   e->hasNameError = FALSE;
03009 
03010   e->used = FALSE;
03011   e->lset = FALSE;
03012 
03013   e->info = (uinfo) dmalloc (sizeof (*e->info));
03014   e->info->datatype = (udinfo) dmalloc (sizeof (*e->info->datatype));
03015   e->info->datatype->abs = abs;
03016   e->info->datatype->mut = mut;
03017   e->info->datatype->type = ctype_undefined;
03018 
03019   if (uentry_isDeclared (e))
03020     {
03021       uentry_setDefined (e, f);
03022     }
03023 
03024   if (ynm_isOn (abs) && !(uentry_isCodeDefined (e)))
03025     {
03026       sRef_setNullState (e->sref, NS_ABSNULL, uentry_whereDeclared (e));
03027     }
03028 
03029   return (e);
03030 }
03031 
03032 /*@notnull@*/ uentry
03033   uentry_makeDatatype (cstring n, ctype t, ynm mut, ynm abs, 
03034                        fileloc f)
03035 {
03036   return (uentry_makeDatatypeAux (n, t, mut, abs, f, FALSE));
03037 }
03038 
03039 /*@notnull@*/ uentry uentry_makeBoolDatatype (ynm abs)
03040 {
03041   uentry ret = uentry_makeDatatypeAux (context_getBoolName (),
03042                                        ctype_bool, NO, abs, 
03043                                        fileloc_getBuiltin (),
03044                                        FALSE);
03045   
03046   ret->info->datatype->type = ctype_bool;
03047   return ret;
03048 }
03049 
03050 /*
03051 ** iters
03052 */
03053 
03054 static /*@only@*/ /*@notnull@*/ uentry 
03055   uentry_makeIterAux (cstring n, typeIdSet access, ctype ct, 
03056                       /*@only@*/ fileloc f)
03057 {
03058   uentry e = uentry_alloc ();
03059 
03060   e->ukind = KITER;
03061   e->uname = cstring_copy (n);
03062   e->utype = ct;
03063   e->sref  = sRef_makeUnknown ();
03064   e->storageclass = SCNONE;
03065   e->used = FALSE;
03066   e->lset = FALSE;
03067 
03068   uentry_setSpecDef (e, f);
03069 
03070   e->uses = filelocList_new ();
03071   e->isPrivate = FALSE;
03072   e->hasNameError = FALSE;
03073 
03074   e->info = (uinfo) dmalloc (sizeof (*e->info));
03075   e->info->iter = (uiinfo) dmalloc (sizeof (*e->info->iter));
03076   e->info->iter->access = access;
03077   e->info->iter->mods = sRefSet_undefined;
03078   e->info->iter->globs = globSet_undefined;
03079 
03080   uentry_checkIterArgs (e);
03081   return (e);
03082 }
03083 
03084 /*@notnull@*/ uentry uentry_makeIter (cstring n, ctype ct, fileloc f)
03085 {
03086   return (uentry_makeIterAux (n, context_fileAccessTypes (), ct, f));
03087 }
03088 
03089 static /*@notnull@*/ uentry
03090 uentry_makeEndIterAux (cstring n, typeIdSet access, /*@only@*/ fileloc f)
03091 {
03092   uentry e = uentry_alloc ();
03093 
03094   /* e->shallowCopy = FALSE; */
03095   e->ukind = KENDITER;
03096   e->storageclass = SCNONE;
03097   e->uname = message ("end_%s", n);
03098   e->utype = ctype_unknown;
03099   e->sref  = sRef_makeUnknown ();
03100 
03101   uentry_setSpecDef (e, f);
03102 
03103   e->used = FALSE;
03104   e->lset = FALSE;
03105 
03106   e->uses = filelocList_new ();
03107   e->isPrivate = FALSE;
03108   e->hasNameError = FALSE;
03109 
03110   e->info = (uinfo) dmalloc (sizeof (*e->info));
03111   e->info->enditer = (ueinfo) dmalloc (sizeof (*e->info->enditer));
03112 
03113   e->info->enditer->access = access;
03114 
03115   return (e);
03116 }
03117 
03118 /*@notnull@*/ /*@only@*/ uentry uentry_makeEndIter (cstring n, fileloc f)
03119 {
03120   return (uentry_makeEndIterAux (n, context_fileAccessTypes (), f));
03121 }
03122 
03123 /*
03124 ** tags
03125 */
03126 
03127 static /*@only@*/ /*@notnull@*/ uentry 
03128   uentry_makeTagAux (cstring n, ctype t, 
03129                      /*@only@*/ fileloc fl, 
03130                      bool priv, ekind kind)
03131 {
03132   uentry e = uentry_alloc ();
03133   
03134   if (kind != KSTRUCTTAG && kind != KUNIONTAG && kind != KENUMTAG)
03135     {
03136       llbuglit ("uentry_makeTagAux: not a tag type");
03137     }
03138   
03139   e->ukind = kind;
03140   /* e->shallowCopy = FALSE; */
03141   e->uname = cstring_copy (n);
03142 
03143   e->utype = t;
03144   e->sref  = sRef_makeUnknown ();
03145   e->storageclass = SCNONE;
03146 
03147   uentry_setSpecDef (e, fl);
03148   
03149   e->used = FALSE;
03150   e->lset = FALSE;
03151 
03152   e->uses = filelocList_new ();
03153   e->isPrivate = priv;
03154   e->hasNameError = FALSE;
03155 
03156   e->info = (uinfo) dmalloc (sizeof (*e->info));
03157   e->info->datatype = (udinfo) dmalloc (sizeof (*e->info->datatype));
03158   e->info->datatype->abs = NO;
03159   e->info->datatype->mut = (kind == KENUMTAG) ? NO : MAYBE;
03160   e->info->datatype->type = t;
03161 
03162   if (uentry_isDeclared (e))
03163     {
03164       uentry_setDefined (e, fl);
03165     }
03166 
03167   return (e);  
03168 }
03169 
03170 uentry uentry_makeStructTagLoc (cstring n, ctype t)
03171 {
03172   cstring sname = makeStruct (n);
03173   uentry ret = uentry_makeTagAux (sname, t, setLocation (), FALSE, KSTRUCTTAG);
03174 
03175   cstring_free (sname);
03176   return (ret);
03177 }
03178 
03179 /*@only@*/ uentry
03180 uentry_makeStructTag (cstring n, ctype t, fileloc loc)
03181 {
03182   cstring sname = makeStruct (n);
03183   uentry ret = uentry_makeTagAux (sname, t, loc, FALSE, KSTRUCTTAG);
03184 
03185   cstring_free (sname);
03186   return ret;
03187 }
03188 
03189 /*@only@*/ uentry
03190 uentry_makeUnionTag (cstring n, ctype t, fileloc loc)
03191 {
03192   cstring uname = makeUnion (n);
03193   uentry ret = uentry_makeTagAux (uname, t, loc, FALSE, KUNIONTAG);
03194 
03195   cstring_free (uname);
03196   return (ret);
03197 }
03198 
03199 # ifndef NOLCL
03200 uentry
03201 uentry_makeEnumTag (cstring n, ctype t, fileloc loc)
03202 {
03203   cstring ename = makeEnum (n);
03204   uentry ret = uentry_makeTagAux (ename, t, loc, FALSE, KENUMTAG);
03205 
03206   cstring_free (ename);
03207   return ret;
03208 }
03209 # endif
03210 
03211 uentry
03212 uentry_makeUnionTagLoc (cstring n, ctype t)
03213 {
03214   cstring uname = makeUnion (n);
03215   uentry ret = uentry_makeTagAux (uname, t, setLocation (), FALSE, KUNIONTAG);
03216 
03217   cstring_free (uname);
03218   return ret;
03219 }
03220 
03221 uentry
03222 uentry_makeEnumTagLoc (cstring n, ctype t)
03223 {
03224   cstring ename = makeEnum (n);
03225   uentry ret = uentry_makeTagAux (ename, t, setLocation (), FALSE, KENUMTAG);
03226 
03227   cstring_free (ename);
03228   return ret;
03229 }
03230 
03231 bool 
03232 uentry_isStructTag (uentry ue) 
03233 {
03234   return (uentry_isValid (ue) && ue->ukind == KSTRUCTTAG);
03235 }
03236 
03237 bool 
03238 uentry_isUnionTag (uentry ue) 
03239 {
03240   return (uentry_isValid (ue) && ue->ukind == KUNIONTAG);
03241 }
03242 
03243 bool 
03244 uentry_isEnumTag (uentry ue) 
03245 {
03246   return (uentry_isValid (ue) && ue->ukind == KENUMTAG);
03247 }
03248 
03249 bool
03250 uentry_isAnyTag (uentry ue)
03251 {
03252   return (uentry_isStructTag (ue) 
03253           || uentry_isUnionTag (ue)
03254           || uentry_isEnumTag (ue));
03255 }
03256 
03257 static /*@unchecked@*/ /*@only@*/ uentry emarker = NULL;
03258 
03259 extern void uentry_destroyMod (void)
03260    /*@globals killed emarker@*/ /*@modifies emarker@*/
03261 {
03262   static bool wasDestroyed = FALSE;
03263 
03264   llassert (!wasDestroyed);
03265 
03266   if (emarker != NULL)
03267     {
03268       uentry_reallyFree (emarker);
03269     }
03270 
03271   wasDestroyed = TRUE;
03272 }
03273 
03274 uentry
03275 uentry_makeElipsisMarker (void)
03276 {
03277   if (emarker == NULL)
03278     {
03279       emarker = uentry_alloc ();
03280 
03281       emarker->ukind = KELIPSMARKER;
03282       emarker->uname = cstring_makeLiteral ("...");
03283       emarker->utype = ctype_elipsMarker;
03284       emarker->sref  = sRef_undefined;
03285       emarker->storageclass = SCNONE;
03286       emarker->used = FALSE;
03287       emarker->lset = FALSE;
03288       emarker->info = NULL;
03289 
03290       uentry_setSpecDef (emarker, fileloc_undefined);
03291       emarker->uses = filelocList_new ();
03292       emarker->isPrivate = FALSE;
03293       emarker->hasNameError = FALSE;
03294     }
03295 
03296   /*@ignore@*/ return (emarker); /*@end@*/
03297 } 
03298 
03299 /*
03300 ** comparisons
03301 */
03302 
03303 bool
03304 uentry_equiv (uentry p1, uentry p2)
03305 {
03306   if (uentry_compare (p1, p2) != 0)
03307     {
03308       return FALSE;
03309     }
03310   else
03311     {
03312       return TRUE;
03313     }
03314 }
03315 
03316 int
03317 uentry_xcomparealpha (uentry *p1, uentry *p2)
03318 {
03319   int res;
03320 
03321   if ((res = uentry_compare (*p1, *p2)) == 0) {
03322     if ((*p1 != NULL) && (*p2 != NULL)) {
03323       res = cstring_compare ((*p1)->uname,
03324                              (*p2)->uname);
03325     }
03326   }
03327 
03328   return res;
03329 }
03330 
03331 int
03332 uentry_xcompareuses (uentry *p1, uentry *p2)
03333 {
03334   uentry u1 = *p1;
03335   uentry u2 = *p2;
03336 
03337   if (uentry_isValid (u1))
03338     {
03339       if (uentry_isValid (u2))
03340         {
03341           return (-1 * int_compare (filelocList_size (u1->uses), 
03342                                     filelocList_size (u2->uses)));
03343         }
03344       else
03345         {
03346           return 1;
03347         }
03348     }
03349   else
03350     {
03351       if (uentry_isValid (u2))
03352         {
03353           return -1;
03354         }
03355       else
03356         {
03357           return 0;
03358         }
03359     }
03360 }
03361 
03362 int 
03363 uentry_compareStrict (uentry v1, uentry v2)
03364 {
03365   COMPARERETURN (uentry_compare (v1, v2));
03366 
03367   if (v1 != v2 && uentry_isValid (v1) && uentry_isValid (v2))
03368     {
03369       COMPARERETURN (fileloc_compare (v1->whereDeclared, v2->whereDeclared));
03370       COMPARERETURN (fileloc_compare (v1->whereDefined, v2->whereDefined));
03371       COMPARERETURN (fileloc_compare (v1->whereSpecified, v2->whereSpecified));
03372     }
03373 
03374   return 0;
03375 }
03376 
03377 int
03378 uentry_compare (uentry u1, uentry u2)
03379 {
03380   if (u1 == u2) return 0;
03381   
03382   if (uentry_isInvalid (u1)) return -1;
03383   if (uentry_isInvalid (u2)) return 1;
03384 
03385   INTCOMPARERETURN (u1->ukind, u2->ukind);
03386   COMPARERETURN (ctype_compare (u1->utype, u2->utype));
03387   COMPARERETURN (bool_compare (uentry_isPriv (u1), uentry_isPriv (u2)));
03388 
03389   COMPARERETURN (sRef_compare (u1->sref, u2->sref));
03390 
03391   switch (u1->ukind)
03392     {
03393     case KINVALID:
03394     case KELIPSMARKER:
03395       /* bug detected by lclint:  
03396       ** uentry.c:753,14: Return value type bool does not match declared type int: TRUE 
03397       */
03398       return 0;
03399     case KENUMCONST:
03400     case KCONST:
03401       return (multiVal_compare (u1->info->uconst->val,
03402                                 u2->info->uconst->val));
03403     case KSTRUCTTAG: 
03404     case KUNIONTAG: 
03405     case KENUMTAG: 
03406       return (ctype_compare (u1->info->datatype->type, u2->info->datatype->type));
03407     case KITER:
03408       COMPARERETURN (typeIdSet_compare (uentry_accessType (u1), 
03409                                          uentry_accessType (u2)));
03410       return (uentryList_compareParams (uentry_getParams (u1), 
03411                                         uentry_getParams (u2)));
03412     case KENDITER:
03413       return (typeIdSet_compare (uentry_accessType (u1), 
03414                                   uentry_accessType (u2)));
03415     case KFCN:
03416       COMPARERETURN (typeIdSet_compare (uentry_accessType (u1), 
03417                                          uentry_accessType (u2)));
03418       COMPARERETURN (globSet_compare (uentry_getGlobs (u1), 
03419                                       uentry_getGlobs (u2)));
03420       COMPARERETURN (uentryList_compareParams (uentry_getParams (u1), 
03421                                                uentry_getParams (u2)));
03422       COMPARERETURN (generic_compare (u1->info->fcn->specialCode,
03423                                        u2->info->fcn->specialCode));
03424       COMPARERETURN (generic_compare (u1->info->fcn->nullPred,
03425                                        u2->info->fcn->nullPred));
03426 
03427       return (sRefSet_compare (uentry_getMods (u1), uentry_getMods (u2)));
03428     case KVAR:
03429       COMPARERETURN (generic_compare (u1->info->var->kind, u2->info->var->kind));
03430       COMPARERETURN (generic_compare (sRef_getOrigAliasKind (u1->sref),
03431                                       sRef_getOrigAliasKind (u2->sref)));
03432       COMPARERETURN (generic_compare (sRef_getOrigExKind (u1->sref),
03433                                       sRef_getOrigExKind (u2->sref)));
03434       COMPARERETURN (generic_compare (u1->info->var->checked,
03435                                       u2->info->var->checked));
03436       COMPARERETURN (generic_compare (u1->info->var->defstate, 
03437                                       u2->info->var->defstate));
03438       return        (generic_compare (u1->info->var->nullstate, 
03439                                       u2->info->var->nullstate));
03440     case KDATATYPE:
03441       COMPARERETURN (ctype_compare (u1->info->datatype->type,
03442                                     u2->info->datatype->type));
03443       COMPARERETURN (ynm_compare (u1->info->datatype->mut,
03444                                   u2->info->datatype->mut));
03445       return (ynm_compare (u1->info->datatype->abs, u2->info->datatype->abs));
03446     }
03447   
03448   BADEXIT;
03449 }
03450 
03451 /*
03452 ** library format:
03453 **
03454 ** all entries are: <type>[@<info>]*#<name>
03455 **
03456 ** info depends on kind:
03457 */
03458 
03459 static void
03460 advanceField (char **s)
03461 {
03462   checkChar (s, '@');
03463 }
03464 
03465 static void
03466 advanceName (char **s)
03467 {
03468   checkChar (s, '#');
03469 }
03470 
03471 static vkind
03472 vkind_fromInt (int i)
03473 {
03474   if /*@+enumint@*/ (i < VKFIRST || i > VKLAST) /*@=enumint@*/
03475     {
03476       llbuglit ("vkind_fromInt: out of range");
03477     }
03478 
03479   return (vkind)i;
03480 }
03481 
03482 static uentry  
03483   uentry_makeConstantBase (/*@only@*/ cstring name, ctype ct, 
03484                            typeIdSet access, nstate nullstate,
03485                            /*@keep@*/ fileloc loc, /*@only@*/ multiVal m)
03486 {
03487   uentry e = uentry_alloc ();
03488   
03489   e->ukind = KCONST;
03490   e->uname = name;
03491   e->utype = ct;
03492   e->sref  = sRef_makeConst (ct);
03493 
03494   sRef_setNullState (e->sref, nullstate, loc);
03495   e->storageclass = SCNONE;
03496 
03497   if (fileloc_isSpec (loc))
03498     {
03499       e->whereSpecified = loc;
03500       e->whereDeclared = fileloc_undefined;
03501     }
03502   else
03503     {
03504       e->whereSpecified = fileloc_undefined;
03505       e->whereDeclared = loc;
03506     }
03507 
03508   e->whereDefined = fileloc_undefined;
03509   e->uses = filelocList_new ();
03510   e->isPrivate = FALSE;
03511   e->hasNameError = FALSE;
03512 
03513   e->used = FALSE;
03514   e->lset = FALSE;
03515 
03516   e->info = (uinfo) dmalloc (sizeof (*e->info));
03517   e->info->uconst = (ucinfo) dmalloc (sizeof (*e->info->uconst));
03518   e->info->uconst->val = m;
03519   e->info->uconst->access = access;
03520 
03521   sRef_storeState (e->sref);
03522 
03523   return (e);
03524 }
03525 
03526 static /*@only@*/ uentry  
03527   uentry_makeVariableBase (/*@only@*/ cstring name, ctype ct, vkind kind, 
03528                            sstate defstate, nstate isnull, alkind aliased,
03529                            exkind exp, chkind checked, 
03530                            /*@only@*/ fileloc loc)
03531 {
03532   uentry e = uentry_alloc ();
03533 
03534   e->ukind = KVAR;
03535   e->uname = name;
03536   e->utype = ct;
03537   e->storageclass = SCNONE;
03538 
03539   e->sref  = sRef_makeType (ct);
03540   sRef_setNullState (e->sref, isnull, loc);
03541 
03542   e->whereDefined = fileloc_undefined;
03543 
03544   if (fileloc_isSpec (loc))
03545     {
03546       e->whereSpecified = loc;
03547       e->whereDeclared = fileloc_undefined;
03548     }
03549   else
03550     {
03551       e->whereSpecified = fileloc_undefined;
03552       e->whereDeclared = loc;
03553     }
03554 
03555   e->isPrivate = FALSE;
03556   e->hasNameError = FALSE;
03557 
03558   e->used = FALSE;
03559   e->lset = FALSE;
03560 
03561   e->uses = filelocList_new ();
03562 
03563   e->info = (uinfo) dmalloc (sizeof (*e->info));
03564   e->info->var = (uvinfo) dmalloc (sizeof (*e->info->var));
03565   e->info->var->kind = kind;
03566   e->info->var->checked = checked;
03567   e->info->var->defstate = defstate;
03568 
03569   sRef_setDefState (e->sref, defstate, loc);
03570 
03571   e->info->var->nullstate = sRef_getNullState (e->sref);
03572 
03573   sRef_setExKind (e->sref, exp, loc);
03574   sRef_setAliasKind (e->sref, aliased, loc);
03575 
03576   sRef_storeState (e->sref);
03577   return (e);
03578 }
03579 
03580 static /*@only@*/ uentry  
03581 uentry_makeDatatypeBase (/*@only@*/ cstring name, ctype ct, ynm abs, 
03582                          ynm mut, ctype rtype, alkind ak, exkind exp, 
03583                          sstate defstate, nstate isnull,
03584                          /*@only@*/ fileloc loc)
03585 {
03586   uentry e = uentry_alloc ();
03587 
03588   e->ukind = KDATATYPE;
03589   /* e->shallowCopy = FALSE; */
03590   e->uname = name;
03591   e->utype = ct;
03592   e->storageclass = SCNONE;
03593   e->sref  = sRef_makeUnknown ();
03594 
03595   /*
03596   ** This is only setting null state.  (I think?)
03597   */
03598 
03599   if (ctype_isUA (ct))
03600     {
03601       uentry te = usymtab_getTypeEntrySafe (ctype_typeId (ct));
03602 
03603       if (uentry_isValid (te))
03604         {
03605           sRef_setStateFromUentry (e->sref, te);
03606         }
03607       else
03608         {
03609           /* problem for recursive type definitions */
03610         }
03611     }
03612   
03613   sRef_setAliasKind (e->sref, ak, loc);
03614   sRef_setExKind (e->sref, exp, loc);
03615 
03616   sRef_setDefState (e->sref, defstate, loc);
03617 
03618   if (ynm_isOn (abs) && ctype_isUnknown (ct) && isnull == NS_UNKNOWN)
03619     {
03620       isnull = NS_ABSNULL;
03621     }
03622 
03623   sRef_mergeNullState (e->sref, isnull);
03624 
03625   e->whereDefined = fileloc_copy (loc); /*< bogus!  (but necessary for lexer) >*/
03626 
03627   if (fileloc_isSpec (loc))
03628     {
03629       e->whereSpecified = loc;
03630       e->whereDeclared = fileloc_undefined;
03631     }
03632   else
03633     {
03634       e->whereSpecified = fileloc_undefined;
03635       e->whereDeclared = loc;
03636     }
03637   
03638   e->isPrivate = FALSE;
03639   e->hasNameError = FALSE;
03640 
03641   e->used = FALSE;
03642   e->lset = FALSE;
03643   e->uses = filelocList_new ();
03644 
03645   e->info = (uinfo) dmalloc (sizeof (*e->info));
03646   e->info->datatype = (udinfo) dmalloc (sizeof (*e->info->datatype));
03647   e->info->datatype->abs = abs;
03648   e->info->datatype->mut = mut;
03649   e->info->datatype->type = rtype;
03650   
03651   sRef_storeState (e->sref);
03652 
03653   return (e);
03654 }
03655 
03656 # ifndef NOLCL
03657 static void uentry_setHasGlobs (uentry ue)
03658 {
03659   llassert (uentry_isFunction (ue));
03660 
03661   ue->info->fcn->hasGlobs = TRUE;
03662 }
03663 
03664 static void uentry_setHasMods (uentry ue)
03665 {
03666   llassert (uentry_isFunction (ue));
03667 
03668   ue->info->fcn->hasMods = TRUE;
03669 }
03670 # endif
03671 
03672 bool uentry_hasGlobs (uentry ue)
03673 {
03674   if (uentry_isFunction (ue))
03675     {
03676       return (ue->info->fcn->hasGlobs);
03677     }
03678 
03679   return FALSE;
03680 }
03681 
03682 bool uentry_hasSpecialClauses (uentry ue)
03683 {
03684   return (uentry_isFunction (ue) && specialClauses_isDefined (ue->info->fcn->specclauses));
03685 }
03686 
03687 specialClauses uentry_getSpecialClauses (uentry ue)
03688 {
03689   llassert (uentry_isFunction (ue));
03690   return ue->info->fcn->specclauses;
03691 }
03692 
03693 bool uentry_hasMods (uentry ue)
03694 {
03695   if (uentry_isFunction (ue))
03696     {
03697       return (ue->info->fcn->hasMods);
03698     }
03699 
03700   return FALSE;
03701 }
03702 
03703 static uentry  
03704   uentry_makeFunctionBase (/*@only@*/ cstring name, ctype ct, 
03705                            typeIdSet access, 
03706                            bool hasGlobs, /*@only@*/ globSet globs, 
03707                            bool hasMods, /*@only@*/ sRefSet mods, 
03708                            alkind ak, exkind exp, 
03709                            sstate defstate, nstate isnull,
03710                            exitkind exitCode,
03711                            specCode sCode,
03712                            qual nullPred,
03713                            /*@only@*/ specialClauses specclauses,
03714                            /*@only@*/ fileloc loc)
03715 {
03716   uentry e = uentry_alloc ();
03717   ctype ret;
03718 
03719   /* e->shallowCopy = FALSE; */
03720   e->ukind = KFCN;
03721   e->uname = name;
03722   e->utype = ct;
03723   e->storageclass = SCNONE;
03724 
03725   if (ctype_isFunction (ct))
03726     {
03727       ret = ctype_returnValue (ct);
03728     }
03729   else
03730     {
03731       if (ctype_isKnown (ct))
03732         {
03733           llbug (message ("not function: %s", ctype_unparse (ct)));
03734         }
03735 
03736       ret = ctype_unknown;
03737     }
03738 
03739   e->sref  = sRef_makeType (ret);
03740 
03741   if (ctype_isUA (ret))
03742     {
03743       sRef_setStateFromType (e->sref, ret);
03744     }
03745 
03746   sRef_setDefined (e->sref, loc);
03747   sRef_setNullState (e->sref, isnull, loc);
03748 
03749   sRef_setAliasKind (e->sref, ak, loc);
03750   sRef_setExKind (e->sref, exp, loc);
03751   sRef_setDefState (e->sref, defstate, loc);
03752 
03753   e->whereSpecified = loc;
03754   e->whereDefined = fileloc_undefined;
03755 
03756   e->isPrivate = FALSE;
03757   e->hasNameError = FALSE;
03758 
03759   e->used = FALSE;
03760   e->lset = FALSE;
03761   e->uses = filelocList_new ();  
03762 
03763   e->info = (uinfo) dmalloc (sizeof (*e->info));
03764   e->info->fcn = (ufinfo) dmalloc (sizeof (*e->info->fcn));
03765   
03766   e->info->fcn->exitCode = exitCode;
03767   e->info->fcn->specialCode = sCode;
03768   e->info->fcn->nullPred = nullPred;
03769   e->info->fcn->access = access;
03770 
03771   e->info->fcn->specclauses = specclauses;
03772   e->info->fcn->hasGlobs = hasGlobs;
03773   e->info->fcn->globs = globs;
03774 
03775   e->info->fcn->hasMods = hasMods;
03776   e->info->fcn->mods = mods;
03777 
03778   e->info->fcn->defparams = uentryList_undefined; 
03779   e->whereDeclared = fileloc_undefined;
03780 
03781   sRef_storeState (e->sref);
03782 
03783   return (e);
03784 }
03785 
03786 static /*@only@*/ uentry  
03787   uentry_makeTagBase (/*@only@*/ cstring name, ekind tagkind, 
03788                       ctype ct, ctype rtype, /*@only@*/ fileloc loc)
03789 {
03790   uentry e = uentry_alloc ();
03791   
03792   if (tagkind != KSTRUCTTAG && tagkind != KUNIONTAG && tagkind != KENUMTAG)
03793     {
03794       llbuglit ("uentry_makeTagBase: not a tag type");
03795     }
03796 
03797   /* e->shallowCopy = FALSE; */
03798   e->ukind = tagkind;
03799   e->uname = name;
03800   e->utype = ct;
03801   e->sref  = sRef_makeUnknown ();
03802   e->storageclass = SCNONE;
03803 
03804   if (fileloc_isSpec (loc))
03805     {
03806       e->whereSpecified = loc;
03807       e->whereDeclared = fileloc_undefined;
03808     }
03809   else
03810     {
03811       e->whereDeclared = loc;
03812       e->whereSpecified = fileloc_undefined;
03813     }
03814 
03815   e->whereDefined = fileloc_undefined;
03816 
03817   e->isPrivate = FALSE;
03818   e->hasNameError = FALSE;
03819 
03820   e->used = FALSE;
03821   e->lset = FALSE;
03822   e->uses = filelocList_new ();
03823 
03824   e->info = (uinfo) dmalloc (sizeof (*e->info));
03825   e->info->datatype = (udinfo) dmalloc (sizeof (*e->info->datatype));
03826   e->info->datatype->abs  = NO;
03827   e->info->datatype->mut  = MAYBE;
03828   e->info->datatype->type = rtype;
03829 
03830   sRef_storeState (e->sref);
03831 
03832   return (e);  
03833 }
03834 
03835 static uentry  
03836   uentry_makeIterBase (/*@only@*/ cstring name, typeIdSet access, 
03837                        ctype ct, /*@only@*/ fileloc loc)
03838 {
03839   uentry e = uentry_alloc ();
03840   
03841   /* e->shallowCopy = FALSE; */
03842   e->ukind = KITER;
03843   e->uname = name;
03844   e->utype = ct;
03845   e->sref  = sRef_makeUnknown ();
03846   e->storageclass = SCNONE;
03847 
03848   if (fileloc_isSpec (loc))
03849     {
03850       e->whereSpecified = loc;
03851       e->whereDeclared = fileloc_undefined;
03852     }
03853   else
03854     {
03855       e->whereDeclared = loc;
03856       e->whereSpecified = fileloc_undefined;
03857     }
03858 
03859   e->whereDefined = fileloc_undefined;
03860   
03861   e->isPrivate = FALSE;
03862   e->hasNameError = FALSE;
03863 
03864   e->used = FALSE;
03865   e->lset = FALSE;
03866   e->uses = filelocList_new ();
03867 
03868   e->info = (uinfo) dmalloc (sizeof (*e->info));
03869   e->info->iter = (uiinfo) dmalloc (sizeof (*e->info->iter));
03870   e->info->iter->access = access;
03871   e->info->iter->mods = sRefSet_undefined;
03872   e->info->iter->globs = globSet_undefined;
03873   
03874   sRef_storeState (e->sref);
03875   return (e);
03876 }
03877 
03878 static uentry  
03879   uentry_makeEndIterBase (/*@only@*/ cstring name, typeIdSet access, 
03880                           /*@only@*/ fileloc loc)
03881 {
03882   uentry e = uentry_alloc ();
03883 
03884   /* e->shallowCopy = FALSE; */
03885   e->ukind = KENDITER;
03886   e->storageclass = SCNONE;
03887   e->uname = name;
03888   e->utype = ctype_unknown;
03889   e->sref  = sRef_makeUnknown ();
03890   
03891   if (fileloc_isSpec (loc))
03892     {
03893       e->whereSpecified = loc;
03894       e->whereDeclared = fileloc_undefined;
03895     }
03896   else
03897     {
03898       e->whereDeclared = loc;
03899       e->whereSpecified = fileloc_undefined;
03900     }
03901 
03902   e->whereDefined = fileloc_undefined;
03903 
03904   e->isPrivate = FALSE;
03905   e->hasNameError = FALSE;
03906 
03907   e->used = FALSE;
03908   e->lset = FALSE;
03909   e->uses = filelocList_new ();
03910 
03911   e->info = (uinfo) dmalloc (sizeof (*e->info));
03912   e->info->enditer = (ueinfo) dmalloc (sizeof (*e->info->enditer));
03913   e->info->enditer->access = access;
03914   sRef_storeState (e->sref);
03915 
03916   return (e);
03917 }
03918 
03919 void uentry_markFree (/*@unused@*/ /*@owned@*/ uentry u)
03920 {
03921   /* should save u */
03922 /*@-mustfree@*/
03923 }
03924 /*@=mustfree@*/
03925 
03926 /*@only@*/ uentry
03927 uentry_undump (ekind kind, fileloc loc, char **s)
03928 {
03929   uentry ue;
03930   
03931   if (**s == '!')
03932     {
03933       checkChar (s, '!');
03934       checkChar (s, '.');
03935       ue = uentry_makeElipsisMarker ();
03936     }
03937   else
03938     {
03939       ctype ct = ctype_undump (s);
03940       cstring name;
03941 
03942       switch (kind)
03943         {
03944         case KVAR:
03945           {
03946             vkind  tkind;
03947             sstate defstate;
03948             nstate isnull;
03949             alkind aliased;
03950             exkind exp;
03951             chkind checked;
03952             
03953             checkChar (s, '|');
03954 
03955             if (optCheckChar (s, '@'))
03956               {
03957                 tkind = vkind_fromInt (getInt (s));
03958                 checkChar (s, '|');
03959               }
03960             else
03961               {
03962                 tkind = VKPARAM;
03963               }
03964 
03965             if (optCheckChar (s, '$'))
03966               {
03967                 defstate = SS_UNKNOWN;
03968                 isnull = NS_UNKNOWN;
03969                 aliased = AK_IMPTEMP;
03970                 exp = XO_UNKNOWN;
03971                 checked = CH_UNKNOWN;
03972               }         
03973             else if (optCheckChar (s, '&'))
03974               {
03975                 defstate = SS_DEFINED;
03976                 isnull = NS_UNKNOWN;
03977                 aliased = AK_IMPTEMP;
03978                 exp = XO_UNKNOWN;
03979                 checked = CH_UNKNOWN;
03980               }         
03981             else if (optCheckChar (s, '^'))
03982               {
03983                 defstate = SS_UNKNOWN;
03984                 isnull = NS_UNKNOWN;
03985                 aliased = AK_IMPTEMP;
03986                 exp = XO_UNKNOWN;
03987                 checked = CH_UNKNOWN;
03988               }         
03989             else
03990               {
03991                 defstate = sstate_fromInt (getInt (s));      
03992                 advanceField (s); isnull = nstate_fromInt (getInt (s));      
03993                 advanceField (s); aliased = alkind_fromInt (getInt (s));      
03994 
03995                 if (optCheckChar (s, '&'))
03996                   {
03997                     exp = XO_UNKNOWN;
03998                     checked = CH_UNKNOWN;
03999                   }
04000                 else
04001                   {
04002                     advanceField (s); exp = exkind_fromInt (getInt (s));      
04003                     advanceField (s); checked = (chkind) (getInt (s));      
04004                   }
04005               }
04006 
04007             advanceName (s);
04008             name = getStringWord (s);
04009             
04010             ue = uentry_makeVariableBase (name, ct, tkind, defstate, 
04011                                           isnull, aliased, exp, 
04012                                           checked, fileloc_copy (loc));
04013           }
04014           break;
04015         case KDATATYPE: 
04016           {
04017             ynm abs;
04018             ynm mut;
04019             ctype rtype;
04020             sstate defstate;
04021             nstate isnull;
04022             alkind aliased;
04023             exkind exp;
04024 
04025             advanceField (s); abs = ynm_fromCodeChar (loadChar (s));
04026             advanceField (s); mut = ynm_fromCodeChar (loadChar (s));
04027             advanceField (s); defstate = sstate_fromInt (getInt (s));      
04028             advanceField (s); isnull = nstate_fromInt (getInt (s));      
04029             advanceField (s); aliased = alkind_fromInt (getInt (s));      
04030             advanceField (s); exp = exkind_fromInt (getInt (s));      
04031             advanceField (s); rtype = ctype_undump (s);
04032             advanceName (s); 
04033             name = getStringWord (s);
04034 
04035             ue = uentry_makeDatatypeBase (name, ct, abs, mut, rtype, 
04036                                           aliased, exp, defstate, isnull, 
04037                                           fileloc_copy (loc));
04038           }
04039           break;
04040         case KFCN:
04041           {
04042             alkind     ak;
04043             exkind     exp;
04044             sstate     defstate;
04045             nstate     isnull;
04046             exitkind   exitCode;
04047             specCode   specc;
04048             qual       nullPred;
04049             typeIdSet access;
04050             bool       hasGlobs;
04051             globSet    globs;
04052             bool       hasMods;
04053             sRefSet    mods;
04054             specialClauses specclauses;
04055 
04056             if (optCheckChar (s, '$'))
04057               {
04058                 defstate = SS_DEFINED;
04059                 isnull = NS_UNKNOWN;
04060                 exitCode = XK_UNKNOWN;
04061                 specc = SPC_NONE;
04062                 nullPred = QU_UNKNOWN;
04063               }
04064             else
04065               {
04066                 advanceField (s); defstate = sstate_fromInt (getInt (s)); 
04067                 advanceField (s); isnull = nstate_fromInt (getInt (s)); 
04068                 advanceField (s); exitCode = exitkind_fromInt (getInt (s)); 
04069                 advanceField (s); specc = specCode_fromInt (getInt (s)); 
04070                 advanceField (s); nullPred = qual_fromInt (getInt (s)); 
04071               }
04072 
04073             if (optCheckChar (s, '$'))
04074               {
04075                 hasGlobs = FALSE;
04076                 globs = globSet_undefined;
04077                 hasMods = FALSE;
04078                 mods = sRefSet_undefined;
04079               }
04080             else if (optCheckChar (s, '^'))
04081               {
04082                 hasGlobs = TRUE;
04083                 globs = globSet_undefined;
04084                 hasMods = TRUE;
04085                 mods = sRefSet_undefined;
04086               }
04087             else
04088               {
04089                 advanceField (s); hasGlobs = bool_fromInt (getInt (s));
04090                 advanceField (s); globs  = globSet_undump (s);
04091                 advanceField (s); hasMods = bool_fromInt (getInt (s));
04092                 advanceField (s); mods   = sRefSet_undump (s);      
04093               }
04094 
04095             if (optCheckChar (s, '$'))
04096               {
04097                 ak = AK_UNKNOWN;
04098                 exp = XO_UNKNOWN;
04099               }
04100             else
04101               {
04102                 advanceField (s); ak = alkind_fromInt (getInt (s));
04103                 advanceField (s); exp = exkind_fromInt (getInt (s));      
04104               }
04105 
04106             advanceField (s); access = typeIdSet_undump (s);
04107 
04108             if (optCheckChar (s, '@'))
04109               {
04110                 specclauses = specialClauses_undump (s);
04111               }
04112             else
04113               {
04114                 specclauses = specialClauses_undefined; 
04115               }
04116 
04117             advanceName (s);  name = getStringWord (s);
04118 
04119             ue = uentry_makeFunctionBase (name, ct, access, 
04120                                           hasGlobs, globs, 
04121                                           hasMods, mods, 
04122                                           ak, exp, defstate, isnull, 
04123                                           exitCode, specc, nullPred,
04124                                           specclauses,
04125                                           fileloc_copy (loc));
04126             DPRINTF (("Undump: %s", uentry_unparse (ue)));
04127           }
04128           break;
04129         case KITER:
04130           {
04131             typeIdSet access;
04132             
04133             advanceField (s); access = typeIdSet_undump (s);
04134             advanceName (s);  name = getStringWord (s);
04135             
04136             ue = uentry_makeIterBase (name, access, ct,
04137                                       fileloc_copy (loc));
04138           }
04139           break;
04140         case KENDITER:
04141           {
04142             typeIdSet access;
04143 
04144             advanceField (s); access = typeIdSet_undump (s);
04145             advanceName (s);  name = getStringWord (s);
04146             
04147             ue = uentry_makeEndIterBase (name, access, fileloc_copy (loc));
04148           }
04149           break;
04150         case KENUMCONST:  
04151         case KCONST:  
04152           {
04153             typeIdSet access;
04154             multiVal val;
04155             nstate nullstate;
04156 
04157             if (optCheckChar (s, '$'))
04158               {
04159                 val = multiVal_undefined;
04160                 access = typeIdSet_undefined;
04161                 nullstate = NS_UNKNOWN;
04162               }
04163             else
04164               {
04165                 advanceField (s); val = multiVal_undump (s);
04166                 advanceField (s); access = typeIdSet_undump (s);
04167                 advanceField (s); nullstate = nstate_fromInt (getInt (s));
04168               }
04169 
04170             advanceName (s);  name = getStringWord (s);
04171             
04172             ue = uentry_makeConstantBase (name, ct, access,
04173                                           nullstate, fileloc_copy (loc), val);
04174             break;
04175           }
04176         case KSTRUCTTAG:
04177         case KUNIONTAG:
04178         case KENUMTAG:
04179           {
04180             ctype rtype;
04181             
04182             advanceField (s); rtype = ctype_undump (s);
04183             advanceName (s);  name = getStringWord (s);
04184             ue = uentry_makeTagBase (name, kind, ct, rtype, fileloc_copy (loc));
04185           }
04186           break;
04187         case KINVALID:
04188           llcontbuglit ("uentry_undump: invalid");
04189           ue = uentry_undefined;
04190           break;
04191         case KELIPSMARKER:
04192           llcontbuglit ("uentry_undump: elips marker");
04193           ue = uentry_undefined;
04194           break;
04195         }
04196     }
04197   
04198   return (ue);
04199 }
04200 
04201 cstring
04202 uentry_dump (uentry v)
04203 {
04204   return (uentry_dumpAux (v, FALSE));
04205 }
04206 
04207 cstring
04208 uentry_dumpParam (uentry v)
04209 {
04210   llassertprint (uentry_isVariable (v) || uentry_isElipsisMarker (v),
04211                  ("dump: %s", uentry_unparseFull (v)));
04212 
04213   return (uentry_dumpAux (v, TRUE));
04214 }
04215 
04216 static cstring
04217 uentry_dumpAux (uentry v, bool isParam)
04218 {
04219   llassert (uentry_isValid (v));
04220 
04221   DPRINTF (("Dumping entry: %s", uentry_unparseFull (v)));
04222 
04223   switch (v->ukind)
04224     {
04225     case KINVALID: 
04226       llcontbuglit ("uentry_dump: invalid entry"); 
04227       return cstring_undefined;
04228     case KELIPSMARKER: 
04229       return (message ("!."));
04230     case KVAR:     
04231       {
04232         cstring sdump;
04233         vkind vk  = v->info->var->kind;
04234         sstate dss = sRef_getDefState (v->sref);
04235         nstate nst = sRef_getNullState (v->sref);
04236         alkind alk = sRef_getAliasKind (v->sref);
04237         exkind exk = sRef_getExKind (v->sref);
04238         chkind chk = v->info->var->checked;
04239 
04240         DPRINTF (("Dumping var"));
04241 
04242         if (dss == SS_UNKNOWN
04243             && nst == NS_UNKNOWN
04244             && alk == AK_IMPTEMP
04245             && exk == XO_UNKNOWN
04246             && chk == CH_UNKNOWN)
04247           {
04248             sdump = cstring_makeLiteral ("$");
04249           }
04250         else if (dss == SS_DEFINED
04251                  && nst == NS_UNKNOWN
04252                  && alk == AK_IMPTEMP
04253                  && exk == XO_UNKNOWN
04254                  && chk == CH_UNKNOWN)
04255           {
04256             sdump = cstring_makeLiteral ("&");
04257           }
04258         else if (dss == SS_UNKNOWN
04259                  && nst == NS_UNKNOWN
04260                  && alk == AK_UNKNOWN
04261                  && exk == XO_UNKNOWN
04262                  && chk == CH_UNKNOWN)
04263           {
04264             sdump = cstring_makeLiteral ("^");
04265           }
04266         else if (exk == XO_UNKNOWN
04267                  && chk == CH_UNKNOWN)
04268           {
04269             sdump = message ("%d@%d@%d&",
04270                              (int) dss,
04271                              (int) nst,
04272                              (int) alk);
04273           }
04274         else
04275           {
04276             sdump = message ("%d@%d@%d@%d@%d",  
04277                      (int) dss,
04278                              (int) nst,
04279                              (int) alk,
04280                              (int) exk,
04281                              (int) chk);
04282           }
04283         
04284 
04285         if (vk != VKPARAM)
04286           {
04287             return (message ("%q|@%d|%q#%s", 
04288                              ctype_dump (v->utype), 
04289                              (int) vk,
04290                              sdump,
04291                              isParam ? cstring_undefined : v->uname));
04292           }
04293         else
04294           {
04295             return (message ("%q|%q#%s", 
04296                              ctype_dump (v->utype), 
04297                              sdump,
04298                              isParam ? cstring_undefined : v->uname));
04299           }
04300 
04301       }
04302     case KDATATYPE: 
04303       return (message ("%q@%s@%s@%d@%d@%d@%d@%q#%s", 
04304                        ctype_dump (v->utype),
04305                        ynm_unparseCode (v->info->datatype->abs),
04306                        ynm_unparseCode (v->info->datatype->mut),
04307                        (int) sRef_getDefState (v->sref),
04308                        (int) sRef_getNullState (v->sref),
04309                        (int) sRef_getAliasKind (v->sref),
04310                        (int) sRef_getExKind (v->sref),
04311                        ctype_dump (v->info->datatype->type),
04312                        v->uname));
04313     case KFCN:
04314       {
04315         cstring sdump, gdump, adump;
04316         alkind alk = sRef_getAliasKind (v->sref);
04317         exkind exk = sRef_getExKind (v->sref);
04318 
04319         if (sRef_getDefState (v->sref) == SS_DEFINED
04320             && !nstate_isKnown (sRef_getNullState (v->sref))
04321             && !exitkind_isKnown (v->info->fcn->exitCode)
04322             && v->info->fcn->specialCode == SPC_NONE
04323             && v->info->fcn->nullPred == QU_UNKNOWN)
04324           {
04325             sdump = cstring_makeLiteral ("$");
04326           }
04327         else
04328           {
04329             sdump = message ("@%d@%d@%d@%d@%d",
04330                              (int) sRef_getDefState (v->sref),
04331                              (int) sRef_getNullState (v->sref),
04332                              (int) v->info->fcn->exitCode,
04333                              (int) v->info->fcn->specialCode,
04334                              (int) v->info->fcn->nullPred);
04335           }
04336 
04337         if (!uentry_hasGlobs(v) && !uentry_hasMods (v))
04338           {
04339             gdump = cstring_makeLiteral ("$");
04340           }
04341         else if (uentry_hasGlobs (v) && globSet_isEmpty (uentry_getGlobs (v))
04342                  && uentry_hasMods (v) && sRefSet_isEmpty (uentry_getMods (v)))
04343           {
04344             gdump = cstring_makeLiteral ("^");
04345           }
04346         else
04347           {
04348             gdump = message ("@%s@%q@%s@%q",
04349                              bool_dump (uentry_hasGlobs (v)),
04350                              globSet_dump (uentry_getGlobs (v)),
04351                              bool_dump (uentry_hasMods (v)),
04352                              sRefSet_dump (uentry_getMods (v)));
04353           }
04354 
04355         if (alk == AK_UNKNOWN && exk == XO_UNKNOWN)
04356           {
04357             adump = cstring_makeLiteral ("$");
04358           }
04359         else
04360           {
04361             adump = message ("@%d@%d", (int) alk, (int) exk);
04362           }
04363 
04364         if (uentry_hasSpecialClauses (v))
04365           {
04366             return (message ("%q%q%q%q@%q@%q#%s",
04367                              ctype_dump (v->utype),
04368                              sdump,
04369                              gdump,
04370                              adump,
04371                              typeIdSet_dump (uentry_accessType (v)),
04372                              specialClauses_dump (v->info->fcn->specclauses),
04373                              v->uname));
04374           }
04375         else
04376           {
04377             return (message ("%q%q%q%q@%q#%s",
04378                              ctype_dump (v->utype),
04379                              sdump,
04380                              gdump,
04381                              adump,
04382                              typeIdSet_dump (uentry_accessType (v)),
04383                              v->uname));
04384           }
04385       }
04386     case KITER:
04387       return (message ("%q@%q#%s",
04388                        ctype_dump (v->utype),
04389                        typeIdSet_dump (v->info->iter->access),
04390                        v->uname));
04391     case KENDITER:
04392       return (message ("%q@%q#%s",
04393                        ctype_dump (v->utype),
04394                        typeIdSet_dump (uentry_accessType (v)),
04395                        v->uname));
04396     case KENUMCONST:  
04397     case KCONST:  
04398       {
04399         cstring sdump;
04400 
04401         if (multiVal_isUnknown (v->info->uconst->val)
04402             && typeIdSet_isEmpty (uentry_accessType (v))
04403             && (sRef_getNullState (v->sref) == NS_UNKNOWN))
04404           {
04405             sdump = cstring_makeLiteral ("$");
04406           }
04407         else
04408           {
04409             sdump = message ("@%q@%q@%d",
04410                              multiVal_dump (v->info->uconst->val),
04411                              typeIdSet_dump (uentry_accessType (v)),
04412                              (int) sRef_getNullState (v->sref));
04413           }
04414 
04415         return (message ("%q%q#%s", 
04416                          ctype_dump (v->utype), 
04417                          sdump,
04418                          v->uname));
04419       }
04420     case KSTRUCTTAG:
04421     case KUNIONTAG:
04422     case KENUMTAG:
04423       return (message ("%q@%q#%s", 
04424                        ctype_dump (v->utype), 
04425                        ctype_dump (v->info->datatype->type), v->uname));
04426     }
04427 
04428   BADEXIT;
04429 }
04430 
04431 /*@only@*/ cstring
04432 uentry_unparseAbbrev (uentry v)
04433 {
04434   if (!uentry_isVariable (v))
04435     {
04436       llcontbuglit ("uentry_unparseAbbrev: not variable");
04437       return uentry_unparse (v);
04438     }
04439 
04440   return (message ("%s %q", ctype_unparseDeep (v->utype), uentry_getName (v)));
04441 }
04442 
04443 /*@only@*/ cstring
04444 uentry_unparse (uentry v)
04445 {
04446   cstring st;
04447 
04448     if (uentry_isUndefined (v)) return (cstring_makeLiteral ("<undefined>"));
04449   if (uentry_isElipsisMarker (v)) return (cstring_makeLiteral ("..."));
04450 
04451   st = uentry_getName (v);
04452 
04453   if (cstring_isDefined (st))
04454     {
04455       return (ctype_unparseDeclaration (v->utype, st)); 
04456     }
04457   else
04458     {
04459       cstring_free (st);
04460       return (cstring_copy (ctype_unparse (v->utype)));
04461     }
04462 }
04463 
04464 /*@only@*/ cstring
04465 uentry_unparseFull (uentry v)
04466 {
04467   if (uentry_isUndefined (v))
04468     {
04469       return (cstring_makeLiteral ("<undefined>"));
04470     }
04471   else if (uentry_isDatatype (v))
04472     {
04473       return (message ("[%d] [%s] %s %q : %t [%t] %s %s // %q [s: %q; d: %q]",
04474                        (int) v,
04475                        ekind_unparse (v->ukind),
04476                        v->uname,
04477                        uentry_getName (v),
04478                        v->utype,
04479                        ctype_isDefined (v->info->datatype->type) 
04480                           ? v->info->datatype->type : ctype_unknown,
04481                        ynm_unparse (v->info->datatype->mut),
04482                        ynm_unparse (v->info->datatype->abs),
04483                        sRef_unparseState (v->sref),
04484                        fileloc_unparse (v->whereSpecified),
04485                        fileloc_unparse (v->whereDefined)));
04486     }
04487   else if (uentry_isFunction (v))
04488     {
04489       return (message ("[%w] = [%s] %q : %t / sref: %q / mods: %q / "
04490                        "globs: %q / [s: %q; decl: %q; def: %q]",
04491                        (long unsigned) v,
04492                        ekind_unparse (v->ukind),
04493                        uentry_getName (v),
04494                        v->utype,
04495                        sRef_unparseFull (v->sref),
04496                        sRefSet_unparse (v->info->fcn->mods),
04497                        globSet_unparse  (v->info->fcn->globs),
04498                        fileloc_unparse (v->whereSpecified),
04499                        fileloc_unparse (v->whereDeclared),
04500                        fileloc_unparse (v->whereDefined)));
04501     }
04502   else if (uentry_isIter (v))
04503     {
04504       return (message ("[%s] %q: %t / %q [s: %q; d: %q]",
04505                        ekind_unparse (v->ukind),
04506                        uentry_getName (v),
04507                        v->utype,
04508                        sRef_unparseFull (v->sref),
04509                        fileloc_unparse (v->whereSpecified),
04510                        fileloc_unparse (v->whereDefined)));
04511     }
04512   else if (uentry_isVariable (v))
04513     {
04514       return 
04515         (message ("[check: %s] / [%w] = [%s] %s : %t %q [s: %q; def: %q; dec: %q] "
04516                   "kind <%d> isout <%d> used <%d>",
04517                   checkedName (v->info->var->checked),
04518                   (long unsigned) v,
04519                   ekind_unparse (v->ukind),
04520                   v->uname,
04521                   v->utype,
04522                   sRef_unparseDeep (v->sref),
04523                   fileloc_unparse (v->whereSpecified),
04524                   fileloc_unparse (v->whereDefined),
04525                   fileloc_unparse (v->whereDeclared),
04526                   (int) v->info->var->kind,
04527                   (int) v->info->var->defstate,
04528                   (int) v->used));
04529     }
04530   else
04531     {
04532       return (message ("[%s] %s : %t %q at [s: %q; d: %q]",
04533                        ekind_unparse (v->ukind),
04534                        v->uname,
04535                        v->utype,
04536                        sRef_unparseFull (v->sref),
04537                        fileloc_unparse (v->whereSpecified),
04538                        fileloc_unparse (v->whereDefined)));
04539       
04540     }
04541 }
04542 
04543 bool uentry_hasAccessType (uentry e)
04544 {
04545   if (uentry_isValid (e))
04546     {
04547       switch (e->ukind)
04548         {
04549         case KITER:
04550           return (!typeIdSet_isEmpty (e->info->iter->access));
04551         case KENDITER:
04552           return (!typeIdSet_isEmpty (e->info->enditer->access));
04553         case KFCN:
04554           return (!typeIdSet_isEmpty (e->info->fcn->access));
04555         case KENUMCONST:
04556         case KCONST:
04557           return (!typeIdSet_isEmpty (e->info->uconst->access));
04558         default:
04559           return FALSE;
04560         }
04561     }
04562 
04563   return FALSE;
04564 }
04565   
04566 typeIdSet uentry_accessType (uentry e)
04567 {
04568   if (uentry_isValid (e))
04569     {
04570       switch (e->ukind)
04571         {
04572         case KITER:
04573           return (e->info->iter->access);
04574         case KENDITER:
04575           return (e->info->enditer->access);
04576         case KFCN:
04577           return (e->info->fcn->access);
04578         case KENUMCONST:
04579         case KCONST:
04580           return (e->info->uconst->access);
04581         default:
04582           break;
04583         }
04584     }
04585 
04586   return typeIdSet_undefined;
04587 }
04588 
04589 bool
04590 uentry_isVariable (uentry e)
04591 {
04592   return (uentry_isVar (e));
04593 }
04594 
04595 bool
04596 uentry_isSpecified (uentry e)
04597 {
04598   return (uentry_isValid (e) && !fileloc_isUndefined (e->whereSpecified));
04599 }
04600 
04601 static bool
04602 uentry_isReallySpecified (uentry e)
04603 {
04604   return (uentry_isValid (e) 
04605           && fileloc_isRealSpec (e->whereSpecified));
04606 }
04607 
04608 bool
04609 uentry_isVar (uentry e)
04610 {
04611   return (!uentry_isUndefined (e) && e->ukind == KVAR);
04612 }
04613 
04614 bool 
04615 uentry_isFakeTag (uentry e)
04616 {
04617   return (uentry_isValid (e) && strchr (cstring_toCharsSafe (e->uname), '!') != 0);
04618 }
04619 
04620 bool
04621 uentry_isDatatype (uentry e)
04622 {
04623   return (!uentry_isUndefined (e) &&
04624           (e->ukind == KDATATYPE || e->ukind == KSTRUCTTAG ||
04625            e->ukind == KUNIONTAG || e->ukind == KENUMTAG));
04626 }
04627 
04628 void
04629 uentry_setAbstract (uentry e)
04630 {
04631   typeId oldid;
04632 
04633   llassert (uentry_isDatatype (e) 
04634             && (ynm_isMaybe (e->info->datatype->abs)));
04635 
04636   oldid = ctype_typeId (e->info->datatype->type);
04637   e->info->datatype->abs = YES;
04638   e->info->datatype->type = ctype_createAbstract (oldid);
04639 }
04640 
04641 void
04642 uentry_setConcrete (uentry e)
04643 {
04644   llassert (uentry_isDatatype (e) 
04645             && (ynm_isMaybe (e->info->datatype->abs)));
04646 
04647   e->info->datatype->abs = NO;
04648 }
04649 
04650 bool
04651 uentry_isAbstractDatatype (uentry e)
04652 {
04653   return (uentry_isDatatype (e) 
04654           && (ynm_isOn (e->info->datatype->abs)));
04655 }
04656 
04657 bool
04658 uentry_isMaybeAbstract (uentry e)
04659 {
04660   return (uentry_isDatatype (e) 
04661           && (ynm_isMaybe (e->info->datatype->abs)));
04662 }
04663 
04664 bool
04665 uentry_isMutableDatatype (uentry e)
04666 {
04667   bool res = uentry_isDatatype (e) 
04668     && (ynm_toBoolRelaxed (e->info->datatype->mut));
04669   
04670   return res;
04671 }
04672 
04673 bool
04674 uentry_isRefCountedDatatype (uentry e)
04675 {
04676   return (uentry_isDatatype (e) && (sRef_isRefCounted (uentry_getSref (e))));
04677 }
04678 
04679 bool
04680 uentry_isParam (uentry u)
04681 {
04682   return (uentry_isVariable (u) && (u->info->var->kind == VKPARAM
04683                                     || u->info->var->kind == VKYIELDPARAM));
04684 }
04685 
04686 bool
04687 uentry_isExpandedMacro (uentry u)
04688 {
04689   return (uentry_isVariable (u) && (u->info->var->kind == VKEXPMACRO));
04690 }
04691 
04692 bool
04693 uentry_isSefParam (uentry u)
04694 {
04695   return (uentry_isVariable (u) 
04696           && (u->info->var->kind == VKSEFPARAM
04697               || u->info->var->kind == VKREFSEFPARAM
04698               || u->info->var->kind == VKSEFRETPARAM
04699               || u->info->var->kind == VKREFSEFRETPARAM));
04700 }
04701 
04702 bool
04703 uentry_isRefParam (uentry u)
04704 {
04705   return (uentry_isVariable (u) 
04706           && (u->info->var->kind == VKREFPARAM
04707               || u->info->var->kind == VKREFYIELDPARAM
04708               || u->info->var->kind == VKREFSEFPARAM
04709               || u->info->var->kind == VKREFSEFRETPARAM));
04710 }
04711 
04712 bool
04713 uentry_isAnyParam (uentry u)
04714 {
04715   return (uentry_isVariable (u) 
04716           && ((u->info->var->kind == VKPARAM)
04717               || (u->info->var->kind == VKSEFPARAM)
04718               || (u->info->var->kind == VKYIELDPARAM)
04719               || (u->info->var->kind == VKRETPARAM)
04720               || (u->info->var->kind == VKSEFRETPARAM)));
04721 }
04722 
04723 sstate 
04724 uentry_getDefState (uentry u)
04725 {
04726   if (uentry_isValid (u))
04727     {
04728       return (sRef_getDefState (u->sref));
04729     }
04730   else
04731     {
04732       return (SS_UNKNOWN);
04733     }
04734 }
04735 
04736 bool
04737 uentry_isOut (uentry u)
04738 {
04739   return ((uentry_isVariable (u) && (u->info->var->defstate == SS_ALLOCATED))
04740           || (uentry_isDatatype (u) && (sRef_isAllocated (u->sref))));
04741 }
04742 
04743 bool
04744 uentry_isPartial (uentry u)
04745 {
04746   return ((uentry_isVariable (u) && (u->info->var->defstate == SS_PARTIAL))
04747           || (uentry_isDatatype (u) && (sRef_isAllocated (u->sref))));
04748 }
04749 
04750 bool
04751 uentry_isStateSpecial (uentry u)
04752 {
04753   return ((uentry_isVariable (u) 
04754            && (u->info->var->defstate == SS_SPECIAL))
04755           || (uentry_isValid (u) && sRef_isStateSpecial (u->sref)));
04756 }
04757 
04758 exitkind uentry_getExitCode (uentry ue) 
04759 {
04760   if (uentry_isFunction (ue))
04761     {
04762       return ue->info->fcn->exitCode;
04763     }
04764   else
04765     {
04766       return XK_UNKNOWN;
04767     }
04768 }
04769 
04770 qual
04771 uentry_nullPred (uentry u)
04772 {
04773   llassert (uentry_isRealFunction (u));
04774 
04775   if (uentry_isFunction (u))
04776     {
04777       return (u->info->fcn->nullPred);
04778     }
04779   else
04780     {
04781       return QU_UNKNOWN;
04782     }
04783 }
04784 
04785 bool
04786 uentry_possiblyNull (uentry u)
04787 {
04788   return ((uentry_isVariable (u) && (nstate_possiblyNull (u->info->var->nullstate)))
04789           || (uentry_isDatatype (u) && (sRef_possiblyNull (u->sref))));
04790 }
04791 
04792 alkind 
04793 uentry_getAliasKind (uentry u)
04794 {
04795   if (uentry_isValid (u))
04796     {
04797       return (sRef_getAliasKind (uentry_getSref (u)));
04798     }
04799   else
04800     {
04801       return AK_UNKNOWN;
04802     }
04803 }
04804 
04805 exkind 
04806 uentry_getExpKind (uentry u)
04807 {
04808   if (uentry_isValid (u))
04809     {
04810       return (sRef_getExKind (uentry_getSref (u)));
04811     }
04812   else
04813     {
04814       return XO_UNKNOWN;
04815     }
04816 }
04817 
04818 bool
04819 uentry_isIter (uentry e)
04820 {
04821   return (!uentry_isUndefined (e) && e->ukind == KITER);
04822 }
04823 
04824 bool
04825 uentry_isEndIter (uentry e)
04826 {
04827   return (!uentry_isUndefined (e) && e->ukind == KENDITER);
04828 }
04829 
04830 bool
04831 uentry_isRealFunction (uentry e)
04832 {
04833   return (uentry_isFunction (e) ||
04834           (uentry_isVariable (e) && ctype_isFunction (uentry_getType (e))));
04835 }
04836 
04837 bool
04838 uentry_hasName (uentry e)
04839 {
04840   if (uentry_isValid (e))
04841     {
04842       cstring s = e->uname;
04843       
04844       return (!(cstring_isEmpty (s) || cstring_equalLit (s, "...")));
04845     }
04846   else
04847     {
04848       return FALSE;
04849     }
04850 }
04851 
04852 bool uentry_hasRealName (uentry e)
04853 {
04854   return (uentry_isValid (e) && cstring_isNonEmpty (e->uname));
04855 }
04856 
04857 
04858 /*@observer@*/ globSet
04859 uentry_getGlobs (uentry l)
04860 {
04861   if (uentry_isInvalid (l)) 
04862     {
04863       return globSet_undefined;
04864     }
04865 
04866   if (l->ukind != KFCN)
04867     {
04868       if (l->ukind != KITER && l->ukind != KENDITER)
04869         {
04870           if (l->ukind == KVAR)
04871             {
04872               llbug (message ("Bad call to uentry_getGlobs (var): %q (%s)", 
04873                               uentry_unparse (l), 
04874                               ekind_unparse (l->ukind)));
04875             }
04876           else
04877             {
04878               llbug (message ("Bad call to uentry_getGlobs: %q (%s)", 
04879                               uentry_unparse (l), 
04880                               ekind_unparse (l->ukind)));
04881             }
04882         }
04883       return globSet_undefined;
04884     }
04885 
04886   return l->info->fcn->globs;
04887 }
04888 
04889 /*@observer@*/ sRefSet
04890 uentry_getMods (uentry l)
04891 {
04892   llassert (uentry_isValid (l));
04893 
04894   if (l->ukind != KFCN && l->ukind != KITER && l->ukind != KENDITER)
04895     {
04896       llcontbug (message ("Bad call to uentry_getMods: %q", uentry_unparse (l)));
04897       return sRefSet_undefined; 
04898     }
04899 
04900   return l->info->fcn->mods;
04901 }
04902 
04903 ekind
04904 uentry_getKind (uentry e)
04905 {
04906   llassert (uentry_isValid (e));
04907 
04908   return (e->ukind);
04909 }
04910 
04911 /*@observer@*/ multiVal uentry_getConstantValue (uentry e)
04912 {
04913   llassert (uentry_isEitherConstant (e));
04914 
04915   return (e->info->uconst->val);
04916 }
04917 
04918 /*@observer@*/ uentryList
04919 uentry_getParams (uentry l)
04920 {
04921   if (uentry_isInvalid (l)) return uentryList_undefined;
04922 
04923   switch (l->ukind)
04924     {
04925     case KFCN:  
04926     case KITER:
04927       {
04928         ctype ct = l->utype;
04929 
04930         if (ctype_isFunction (ct))
04931           {
04932             return (ctype_argsFunction (ct));
04933           }
04934         else
04935           {
04936             return uentryList_undefined;
04937           }
04938       }
04939     case KVAR:  
04940       {
04941         ctype ct = l->utype;
04942 
04943         llassert (ctype_isFunction (ct));
04944         return (ctype_argsFunction (ct));
04945       }
04946     BADDEFAULT;
04947     }
04948   BADEXIT;
04949 }
04950 
04951 /*@observer@*/ cstring
04952 uentry_rawName (uentry e)
04953 {
04954   if (uentry_isValid (e))
04955     {
04956       return (e->uname);
04957     }
04958   else
04959     {
04960       return cstring_undefined;
04961     }
04962 }
04963 
04964 static cstring
04965 uentry_getOptName (uentry e)
04966 {
04967   cstring s = uentry_getName (e);
04968 
04969   if (cstring_isDefined (s))
04970     {
04971       s = cstring_appendChar (s, ' ');
04972     }
04973   
04974   return s;
04975 }
04976 
04977 /*@only@*/ cstring
04978 uentry_getName (uentry e)
04979 {
04980   cstring ret = cstring_undefined;
04981 
04982   if (uentry_isValid (e))
04983     {
04984       
04985       if (uentry_isAnyTag (e))
04986         {
04987           ret = fixTagName (e->uname); 
04988         }
04989       else if (uentry_isAnyParam (e))
04990         {
04991           ret = cstring_copy (fixParamName (e->uname));
04992         }
04993       else
04994         {
04995           ret = cstring_copy (e->uname);
04996         }
04997     }
04998 
04999   return ret;
05000 }
05001 
05002 cstring uentry_getRealName (uentry e)
05003 {
05004   if (uentry_isValid (e))
05005     {
05006       if (uentry_isAnyTag (e))
05007         {
05008           return (cstring_undefined);
05009         }
05010       else
05011         {
05012           return (e->uname);
05013         }
05014     }
05015   return cstring_undefined;
05016 }
05017 
05018 ctype uentry_getType (uentry e)
05019 {
05020   if (uentry_isValid (e))
05021     {
05022       return e->utype;
05023     }
05024   else
05025     {
05026       return ctype_unknown;
05027     }
05028 }
05029 
05030 fileloc uentry_whereLast (uentry e)
05031 {
05032   fileloc loc;
05033 
05034   if (uentry_isInvalid (e)) 
05035     {
05036       return fileloc_undefined;
05037     }
05038   
05039   loc = e->whereDefined;
05040 
05041   if (fileloc_isValid (loc) && !fileloc_isExternal (loc))
05042     {
05043       return loc;
05044     }
05045 
05046   loc = uentry_whereDeclared (e);
05047 
05048   if (fileloc_isValid (loc) && !fileloc_isExternal (loc))
05049     {
05050       return loc;
05051     }
05052 
05053   loc = uentry_whereSpecified (e);
05054   return loc;
05055 }
05056 
05057 fileloc uentry_whereEither (uentry e)
05058 {
05059   if (uentry_isInvalid (e)) return fileloc_undefined;
05060 
05061   if (fileloc_isDefined (e->whereDefined) 
05062       && !fileloc_isExternal (e->whereDefined))
05063     {
05064       return e->whereDefined;
05065     }
05066   else if (fileloc_isDefined (e->whereDeclared))
05067     {
05068       return e->whereDeclared;
05069     }
05070   else
05071     {
05072       return e->whereSpecified;
05073     }
05074 }
05075 
05076 fileloc uentry_whereSpecified (uentry e)
05077 {
05078   if (uentry_isInvalid (e)) return fileloc_undefined;
05079 
05080   return (e->whereSpecified);
05081 }
05082 
05083 fileloc uentry_whereDefined (uentry e)
05084 {
05085   if (uentry_isInvalid (e)) return fileloc_undefined;
05086 
05087   return (e->whereDefined);
05088 }
05089 
05090 fileloc uentry_whereDeclared (uentry e)
05091 {
05092   if (uentry_isInvalid (e)) return fileloc_undefined;
05093 
05094   return (e->whereDeclared);
05095 }
05096 
05097 /*@observer@*/ fileloc
05098 uentry_whereEarliest (uentry e)
05099 {
05100   if (uentry_isInvalid (e)) return fileloc_undefined;
05101   
05102   if (fileloc_isDefined (e->whereSpecified))
05103     {
05104       return (e->whereSpecified);
05105     }
05106   else if (fileloc_isDefined (e->whereDeclared))
05107     {
05108       return (e->whereDeclared);
05109     }
05110   else
05111     {
05112       return e->whereDefined;
05113     }
05114 }
05115 
05116 void
05117 uentry_setFunctionDefined (uentry e, fileloc loc)
05118 {
05119   if (uentry_isValid (e))
05120     {
05121       llassert (uentry_isFunction (e));
05122 
05123       if (fileloc_isUndefined (e->whereDeclared))
05124         {
05125           e->whereDeclared = fileloc_update (e->whereDeclared, loc);
05126         }
05127       
05128       if (!fileloc_isDefined (e->whereDefined))
05129         {
05130           e->whereDefined = fileloc_update (e->whereDefined, loc);
05131         }
05132     }
05133 }
05134 
05135 void
05136 uentry_setDeclDef (uentry e, fileloc f)
05137 {
05138   uentry_setDeclared (e, f);
05139   
05140   if (!uentry_isFunction (e)
05141       && !(uentry_isVariable (e) && uentry_isExtern (e)))
05142     {
05143       uentry_setDefined (e, f);
05144     }
05145 }
05146 
05147 void
05148 uentry_setDeclaredForce (uentry e, fileloc f)
05149 {
05150   llassert (uentry_isValid (e));
05151   e->whereDeclared = fileloc_update (e->whereDeclared, f);
05152 }
05153 
05154 void
05155 uentry_setDeclaredForceOnly (uentry e, fileloc f)
05156 {
05157   llassert (uentry_isValid (e));
05158   fileloc_free (e->whereDeclared);
05159   e->whereDeclared = f;
05160 }
05161 
05162 void
05163 uentry_setDeclaredOnly (uentry e, /*@only@*/ fileloc f)
05164 {
05165   fileloc oldloc;
05166 
05167   llassert (uentry_isValid (e));
05168   oldloc = e->whereDeclared;  
05169 
05170   if (fileloc_isDefined (oldloc))
05171     {
05172       if (fileloc_isLib (oldloc) || fileloc_isImport (oldloc))
05173         {
05174           e->whereDeclared = f;
05175           fileloc_free (oldloc);
05176         }
05177       else
05178         {
05179           fileloc_free (f);
05180         }
05181     }
05182   else
05183     {
05184       e->whereDeclared = f;
05185       fileloc_free (oldloc);
05186     }
05187 }
05188   
05189 void
05190 uentry_setDeclared (uentry e, fileloc f)
05191 {
05192   fileloc oldloc;
05193 
05194   llassert (uentry_isValid (e));
05195   oldloc = e->whereDeclared;  
05196 
05197   if (fileloc_isDefined (oldloc))
05198     {
05199       if (fileloc_isLib (oldloc) || fileloc_isImport (oldloc))
05200         {
05201           e->whereDeclared = fileloc_update (e->whereDeclared, f);
05202         }
05203       else
05204         {
05205           ;
05206         }
05207     }
05208   else
05209     {
05210       e->whereDeclared = fileloc_update (e->whereDeclared, f);
05211     }
05212 }
05213 
05214 void
05215 uentry_clearDefined (uentry e)
05216 {
05217   if (uentry_isValid (e))
05218     {
05219       e->whereDefined = fileloc_update (e->whereDefined, fileloc_undefined);
05220     }
05221 }
05222 
05223 void
05224 uentry_setDefined (uentry e, fileloc f)
05225 {
05226   fileloc oldloc;
05227 
05228   llassert (uentry_isValid (e));
05229   oldloc = e->whereDefined;
05230 
05231   if (fileloc_isDefined (oldloc))
05232     {
05233       if (fileloc_isLib (oldloc) 
05234           || fileloc_isImport (oldloc)
05235           || fileloc_isBuiltin (oldloc) 
05236           || fileloc_isPreproc (oldloc))
05237         {
05238           e->whereDefined = fileloc_update (e->whereDefined, f);
05239         }
05240       else
05241         {
05242           if (fileloc_equal (oldloc, f) || context_processingMacros ())
05243             {
05244               ; /* okay */
05245             }
05246           else
05247             {
05248               if (optgenerror (FLG_REDEF,
05249                                message ("%s %q redefined", 
05250                                         ekind_capName (e->ukind),
05251                                         uentry_getName (e)),
05252                                f))
05253                 {
05254                   llgenindentmsg (message ("Previous definition of %q", 
05255                                            uentry_getName (e)),
05256                                   e->whereDefined);
05257                 }
05258             }
05259         }
05260     }
05261   else
05262     {
05263       e->whereDefined = fileloc_update (e->whereDefined, f);
05264     }
05265 }
05266 
05267 bool
05268 uentry_isCodeDefined (uentry e)
05269 {
05270   return (uentry_isValid (e) && fileloc_isDefined (e->whereDefined));
05271 }
05272 
05273 bool
05274 uentry_isDeclared (uentry e)
05275 {
05276   if (uentry_isValid (e))
05277     {
05278       return (fileloc_isDefined (e->whereDeclared));
05279     }
05280 
05281   return FALSE;
05282 }
05283 
05284 sRef uentry_getSref (uentry e)
05285 {
05286   /* not true, used for functions too (but shouldn't be? */
05287   /* llassertprint (e->ukind == KVAR, ("uentry_getSref: not variable!")); */
05288 
05289   if (uentry_isInvalid (e)) return sRef_undefined;
05290   
05291   return (e->sref);
05292 }
05293 
05294 sRef uentry_getOrigSref (uentry e)
05295 {
05296   if (uentry_isValid (e))
05297     {
05298       sRef sr = sRef_copy (uentry_getSref (e));
05299       
05300       sRef_resetState (sr);
05301       sRef_clearDerived (sr);
05302       
05303       if (uentry_isVariable (e))
05304         {
05305           sRef_setDefState (sr, e->info->var->defstate, fileloc_undefined);
05306           sRef_setNullState (sr, e->info->var->nullstate, fileloc_undefined);
05307         }
05308       
05309       return (sr);
05310     }
05311   else
05312     {
05313       return sRef_undefined;
05314     }
05315 }
05316 
05317 /*
05318 ** requires: uentry e is not in a hashed symbol table
05319 */
05320 
05321 void 
05322 uentry_setName (uentry e, /*@only@*/ cstring n)
05323 {
05324   llassert (uentry_isValid (e));
05325 
05326   cstring_free (e->uname);
05327   e->uname = n;
05328 }
05329 
05330 void
05331 uentry_setType (uentry e, ctype t)
05332 {
05333   if (uentry_isValid (e)) 
05334     {
05335       e->utype = t;
05336       sRef_setType (e->sref, t);
05337     }
05338 }
05339 
05340 void
05341 uentry_resetParams (uentry ue, /*@only@*/ uentryList pn)
05342 {
05343   ctype rct;
05344   ctype rettype = ctype_unknown;
05345   
05346   llassert (uentry_isValid (ue));
05347 
05348   rct = ctype_realType (ue->utype);
05349 
05350   if (uentry_isVariable (ue) && (ctype_isFunction (rct) || ctype_isUnknown (rct)))
05351     {
05352       uentry_makeVarFunction (ue);
05353     }
05354 
05355   llassert (uentry_isFunction (ue));
05356 
05357   if (ctype_isFunction (rct))
05358     {
05359       rettype = ctype_returnValue (rct);
05360     }
05361 
05362   ue->utype = ctype_makeNFParamsFunction (rettype, pn);      
05363 }
05364 
05365 void
05366 uentry_setRefParam (uentry e)
05367 {
05368   
05369   if (!uentry_isVar (e))
05370     {
05371       llbug (message ("uentry_setParam: not variable: %q", uentry_unparse (e)));
05372     }
05373   else
05374     {
05375       if (e->info->var->kind == VKSEFPARAM)
05376         {
05377           e->info->var->kind = VKREFSEFPARAM;
05378         }
05379       else if (e->info->var->kind == VKSEFRETPARAM)
05380         {
05381           e->info->var->kind = VKREFSEFRETPARAM;
05382         }
05383       else if (e->info->var->kind == VKYIELDPARAM)
05384         {
05385           e->info->var->kind = VKREFYIELDPARAM;
05386         }
05387       else
05388         {
05389           e->info->var->kind = VKREFPARAM;
05390         }
05391     }
05392 }
05393 
05394 void
05395 uentry_setParam (uentry e)
05396 {
05397   if (!uentry_isVar (e))
05398     {
05399       if (uentry_isElipsisMarker (e))
05400         {
05401 
05402         }
05403       else
05404         {
05405           llbug (message ("uentry_setParam: not variable: %q", uentry_unparse (e)));
05406         }
05407     }
05408   else
05409     {
05410       cstring oldname;
05411 
05412       if (e->info->var->kind == VKYIELDPARAM 
05413           || e->info->var->kind == VKSEFPARAM
05414           || e->info->var->kind == VKSEFRETPARAM)
05415         {
05416           ;
05417         }
05418       else
05419         {
05420           e->info->var->kind = VKPARAM;
05421         }
05422 
05423       oldname = e->uname;
05424       e->uname = makeParam (e->uname);
05425       cstring_free (oldname);
05426     }
05427 }
05428 
05429 void
05430 uentry_setSref (uentry e, sRef s)
05431 {
05432   if (uentry_isValid (e))
05433     {
05434       if (sRef_isValid (e->sref))
05435         {
05436           sRef_mergeStateQuietReverse (e->sref, s);
05437         }
05438       else
05439         {
05440           e->sref = sRef_saveCopy (s);
05441         }
05442     }
05443 }
05444 
05445 ctype
05446 uentry_getAbstractType (uentry e)
05447 {
05448   llassert (uentry_isDatatype (e));
05449 
05450   /*
05451   ** This assertion removed.
05452   ** Okay to have undefined type, for system types
05453   
05454   llassertprintret (!ctype_isUndefined (e->info->datatype->type),
05455                     ("uentry_getAbstractType %q: undefined", uentry_unparseFull (e)),
05456                     e->utype);
05457                     
05458   */
05459 
05460   if (ctype_isUndefined (e->info->datatype->type))
05461     {
05462       return ctype_unknown;
05463     }
05464 
05465   /*
05466   ** Sadly, a kludge...
05467   */
05468 
05469   if (ctype_isUserBool (e->info->datatype->type)) {
05470     return ctype_bool;
05471   }
05472 
05473   return e->info->datatype->type;
05474 }
05475 
05476 ctype uentry_getRealType (uentry e)
05477 {
05478   ctype ct;
05479   typeId uid = USYMIDINVALID;
05480 
05481   if (uentry_isInvalid (e))
05482     {
05483       return ctype_unknown;
05484     }
05485 
05486   llassertprint (uentry_isDatatype (e), ("not datatype: %s", uentry_unparse (e)));
05487 
05488   if (uentry_isAnyTag (e))
05489     {
05490       return (e->utype);
05491     }
05492   
05493   if (uentry_isAbstractType (e))
05494     {
05495       ct = uentry_getAbstractType (e);      
05496 
05497       if (ctype_isManifestBool (ct)) {
05498         return ct;
05499       }
05500 
05501       llassert (ctype_isUA (ct));
05502       
05503       uid = ctype_typeId (ct);
05504       
05505       if (!context_hasAccess (uid))
05506         {
05507           return (ct);
05508         }
05509     }
05510 
05511   ct = uentry_getType (e);
05512 
05513   /* if (ctype_isUserBool (ct)) return ct; */
05514 
05515   if (ctype_isManifestBool (ct)) {
05516     return ctype_bool;
05517   }
05518   
05519   if (ctype_isUA (ct))
05520     {
05521       usymId iid = ctype_typeId (ct);
05522       
05523       if /*@access usymId@*/ (iid == uid) /*@noaccess usymId@*/
05524         {         
05525           llcontbug (message ("uentry_getRealType: recursive type! %s",
05526                               ctype_unparse (ct)));
05527           return ct;
05528         }
05529       else
05530         {
05531           /* evs 2000-07-25: possible infinite recursion ? */
05532           uentry ue2 = usymtab_getTypeEntry (iid);
05533           llassertprint (ue2 != e, ("Bad recursion: %s", uentry_unparseFull (e)));
05534 
05535           return uentry_getRealType (ue2);
05536         }
05537     }
05538   else
05539     {
05540       return ct;
05541     }
05542 }
05543 
05544 ctype uentry_getForceRealType (uentry e)
05545 {
05546   ctype   ct;
05547   typeId uid = USYMIDINVALID;
05548 
05549   if (uentry_isInvalid (e))
05550     {
05551       return ctype_unknown;
05552     }
05553 
05554   llassertprint (uentry_isDatatype (e), ("not datatype: %s", uentry_unparse (e)));
05555   
05556   if (uentry_isAnyTag (e))
05557     {
05558       return (e->utype);
05559     }
05560   
05561   if (uentry_isAbstractType (e))
05562     {
05563       ct = uentry_getAbstractType (e);      
05564       llassert (ctype_isUA (ct));
05565       
05566       uid = ctype_typeId (ct);
05567       /* no check for access! */
05568     }
05569   
05570   ct = uentry_getType (e);
05571 
05572   /* evs 2000-07-25 */
05573   /* if (ctype_isUserBool (ct)) return ct; */
05574 
05575   if (ctype_isManifestBool (ct)) {
05576     return ctype_bool;
05577   }
05578   
05579   if (ctype_isUA (ct))
05580     {
05581       usymId iid = ctype_typeId (ct);
05582       
05583       if /*@access usymId@*/ (iid == uid) /*@noaccess usymId@*/
05584         {         
05585           llcontbug (message ("uentry_getRealType: recursive type! %s",
05586                               ctype_unparse (ct)));
05587           return ct;
05588         }
05589       else
05590         {
05591           return uentry_getForceRealType (usymtab_getTypeEntry (iid));
05592         }
05593     }
05594   else
05595     {
05596       return ct;
05597     }
05598 }
05599 
05600 uentry uentry_nameCopy (cstring name, uentry e)
05601 {
05602   uentry enew = uentry_alloc ();
05603 
05604   llassert (uentry_isValid (e));
05605 
05606   /* enew->shallowCopy = FALSE; */
05607   enew->ukind = e->ukind;
05608   enew->uname = name;
05609   enew->utype = e->utype;
05610   enew->whereSpecified = fileloc_copy (e->whereSpecified);
05611   enew->whereDefined = fileloc_copy (e->whereDefined);
05612   enew->whereDeclared = fileloc_copy (e->whereDeclared);
05613   enew->sref = sRef_copy (e->sref); 
05614   enew->used = e->used;
05615   enew->lset = FALSE;
05616   enew->isPrivate = e->isPrivate;
05617   enew->hasNameError = FALSE;
05618 
05619   enew->uses = filelocList_new ();
05620 
05621   enew->storageclass = e->storageclass;
05622   enew->info = uinfo_copy (e->info, e->ukind);
05623 
05624   return enew;
05625 }
05626 
05627 void
05628 uentry_setDatatype (uentry e, usymId uid)
05629 {
05630   llassert (uentry_isDatatype (e));
05631 
05632   if (uentry_isAbstractType (e))
05633     {
05634       e->info->datatype->type = ctype_createAbstract (uid);
05635     }
05636   else
05637     {
05638       e->info->datatype->type = ctype_createUser (uid);
05639     }
05640 }
05641 
05642 static void 
05643 uentry_setSpecDef (/*@special@*/ uentry e, /*@keep@*/ fileloc f)
05644    /*@defines e->whereSpecified, e->whereDeclared, e->whereDefined@*/
05645    /*@modifies e@*/
05646 {
05647   llassert (uentry_isValid (e));
05648 
05649   if (fileloc_isSpec (f) || fileloc_isImport (f))
05650     {
05651       e->whereSpecified = f;
05652       e->whereDeclared  = fileloc_undefined;
05653       e->whereDefined  = fileloc_undefined;
05654     }
05655   else
05656     {
05657       e->whereSpecified = fileloc_undefined;
05658       e->whereDeclared  = f;
05659       e->whereDefined  = fileloc_undefined;
05660     }
05661 }
05662 
05663 static void
05664 ucinfo_free (/*@only@*/ ucinfo u)
05665 {
05666   multiVal_free (u->val);
05667   sfree (u);
05668 }
05669 
05670 static void
05671 uvinfo_free (/*@only@*/ uvinfo u)
05672 {
05673   sfree (u);
05674 }
05675 
05676 static void
05677 udinfo_free (/*@only@*/ udinfo u)
05678 {
05679   sfree (u);
05680 }
05681 
05682 static void
05683 ufinfo_free (/*@only@*/ ufinfo u)
05684 {
05685   globSet_free (u->globs);
05686   sRefSet_free (u->mods);
05687   specialClauses_free (u->specclauses);
05688 
05689   sfree (u);
05690 }
05691 
05692 static void
05693 uiinfo_free (/*@only@*/ uiinfo u)
05694 {
05695   sfree (u);
05696 }
05697 
05698 static void
05699 ueinfo_free (/*@only@*/ ueinfo u)
05700 {
05701   sfree (u);
05702 }
05703 
05704 static /*@only@*/ ucinfo
05705 ucinfo_copy (ucinfo u)
05706 {
05707   ucinfo ret = (ucinfo) dmalloc (sizeof (*ret));
05708   
05709   ret->val = multiVal_copy (u->val);
05710   ret->access = u->access;
05711 
05712   return ret;
05713 }
05714 
05715 static /*@only@*/ uvinfo
05716 uvinfo_copy (uvinfo u)
05717 {
05718   uvinfo ret = (uvinfo) dmalloc (sizeof (*ret));
05719   
05720   ret->kind = u->kind;
05721   ret->nullstate = u->nullstate;
05722   ret->defstate = u->defstate;
05723   ret->checked = u->checked;
05724 
05725   return ret;
05726 }
05727 
05728 static /*@only@*/ udinfo
05729 udinfo_copy (udinfo u)
05730 {
05731   udinfo ret = (udinfo) dmalloc (sizeof (*ret));
05732 
05733   ret->abs = u->abs;
05734   ret->mut = u->mut;
05735   ret->type = u->type;
05736 
05737   return ret;
05738 }
05739 
05740 static /*@only@*/ ufinfo
05741 ufinfo_copy (ufinfo u)
05742 {
05743   ufinfo ret = (ufinfo) dmalloc (sizeof (*ret));
05744 
05745   ret->hasGlobs = u->hasGlobs;
05746   ret->hasMods = u->hasMods;
05747   ret->exitCode = u->exitCode;
05748   ret->specialCode = u->specialCode;
05749   ret->nullPred = u->nullPred;
05750   ret->access = u->access;
05751   ret->globs = globSet_newCopy (u->globs);
05752   ret->mods = sRefSet_newCopy (u->mods);
05753   ret->defparams = u->defparams;
05754   ret->specclauses = specialClauses_copy (u->specclauses);
05755 
05756   return ret;
05757 }
05758 
05759 static /*@only@*/ uiinfo
05760 uiinfo_copy (uiinfo u)
05761 {
05762   uiinfo ret = (uiinfo) dmalloc (sizeof (*ret));
05763 
05764   ret->access = u->access;
05765   ret->globs = globSet_newCopy (u->globs);
05766   ret->mods = sRefSet_newCopy (u->mods);
05767 
05768   return (ret);
05769 }
05770 
05771 static /*@only@*/ ueinfo
05772 ueinfo_copy (ueinfo u)
05773 {
05774   ueinfo ret = (ueinfo) dmalloc (sizeof (*ret));
05775 
05776   ret->access = u->access;
05777   return ret;
05778 }
05779 
05780 static void
05781 uinfo_free (uinfo u, ekind kind)
05782 {
05783   switch (kind)
05784     {
05785     case KENUMCONST:
05786     case KCONST:       ucinfo_free (u->uconst); break;
05787     case KVAR:         uvinfo_free (u->var); break;
05788     case KSTRUCTTAG:
05789     case KUNIONTAG:
05790     case KENUMTAG:
05791     case KDATATYPE:    udinfo_free (u->datatype); break;
05792     case KFCN:         ufinfo_free (u->fcn); break;
05793     case KITER:        uiinfo_free (u->iter); break;
05794     case KENDITER:     ueinfo_free (u->enditer); break;
05795     case KELIPSMARKER: break;
05796     case KINVALID:     break;
05797     }
05798   
05799     sfree (u);
05800 }
05801 
05802 static /*@only@*/ /*@null@*/ uinfo
05803 uinfo_copy (uinfo u, ekind kind)
05804 {
05805   if (kind == KELIPSMARKER || kind == KINVALID)
05806     {
05807       return NULL;
05808     }
05809   else
05810     {
05811       uinfo ret = (uinfo) dmalloc (sizeof (*ret));
05812       
05813       switch (kind)
05814         {
05815         case KENUMCONST:
05816         case KCONST:    ret->uconst = ucinfo_copy (u->uconst); break;
05817         case KVAR:      ret->var = uvinfo_copy (u->var); break;
05818         case KSTRUCTTAG:
05819         case KUNIONTAG:
05820         case KENUMTAG:
05821         case KDATATYPE: ret->datatype = udinfo_copy (u->datatype); break;
05822         case KFCN:      ret->fcn = ufinfo_copy (u->fcn); break;
05823         case KITER:     ret->iter = uiinfo_copy (u->iter); break;
05824         case KENDITER:  ret->enditer = ueinfo_copy (u->enditer); break;
05825         BADDEFAULT;
05826         }
05827       return ret;
05828     }
05829 }
05830 
05831 static void
05832 uentry_reallyFree (/*@notnull@*/ /*@only@*/ uentry e)
05833 {
05834   filelocList_free (e->uses);
05835   cstring_free (e->uname);
05836   
05837   uinfo_free (e->info, e->ukind);
05838   
05839   fileloc_free (e->whereSpecified); 
05840   fileloc_free (e->whereDefined); 
05841   fileloc_free (e->whereDeclared); 
05842 
05843   nuentries--;
05844   sfree (e);
05845   }
05846 
05847 extern void uentry_markOwned (/*@owned@*/ uentry u)
05848 {
05849   sfreeEventually (u);
05850 }
05851 
05852 void
05853 uentry_free (/*@only@*/ uentry e)
05854 {
05855   if (uentry_isValid (e) && !uentry_isElipsisMarker (e))
05856     {
05857       uentry_reallyFree (e);
05858     }
05859 }
05860 
05861 /*
05862 ** For uentry's in the global or file scope
05863 */
05864 
05865 void
05866 uentry_freeComplete (/*@only@*/ uentry e)
05867 {
05868   if (uentry_isValid (e) && !uentry_isElipsisMarker (e))
05869     {
05870       /*@i@*/ sRef_free (e->sref);
05871       e->sref = sRef_undefined;
05872       uentry_reallyFree (e);
05873     }
05874 }
05875 
05876 /*
05877 ** requires old->kind != new->kind, old->uname = new->uname
05878 */
05879 
05880 static void
05881 KindConformanceError (/*@unique@*/ uentry old, uentry unew, bool mustConform)
05882 {
05883   llassert (uentry_isValid (old));
05884   llassert (uentry_isValid (unew));
05885 
05886   if (uentry_isEitherConstant (unew)
05887       && (fileloc_isPreproc (uentry_whereDeclared (old))
05888           || ctype_isUnknown (old->utype))
05889       && !uentry_isSpecified (old))
05890     {
05891       ; /* no error */
05892     }
05893   else 
05894     {
05895       if (mustConform)
05896         {
05897           if (!uentry_isDeclared (old))
05898             {
05899               if (uentry_isSpecified (old))
05900                 {
05901                   if (uentry_isSpecified (unew))
05902                     {
05903                       llbuglit ("Respecification!");
05904                     }
05905                   else if (uentry_isDeclared (unew))
05906                     {
05907                       if (optgenerror
05908                           (FLG_INCONDEFS,
05909                            message ("%s %q inconsistently declared as %s: %t",
05910                                     ekind_capName (old->ukind),
05911                                     uentry_getName (unew),
05912                                     ekind_unparseLong (unew->ukind),
05913                                     unew->utype),
05914                            uentry_whereDeclared (unew)))
05915                         {
05916                           uentry_showWhereLast (old);
05917                         }
05918                     }
05919                   else
05920                     {
05921                       BADEXIT;
05922                     }
05923                 }
05924               else
05925                 {
05926                   if (optgenerror
05927                       (FLG_INCONDEFS,
05928                        message ("%s %q inconsistently declared as %s: %t",
05929                                 ekind_capName (old->ukind),
05930                                 uentry_getName (unew),
05931                                 ekind_unparseLong (unew->ukind),
05932                                 unew->utype),
05933                        uentry_whereDeclared (unew)))
05934                     {
05935                       uentry_showWhereLast (old);
05936                     }
05937                 }
05938             }
05939           else
05940             {
05941               llassert (uentry_isDeclared (unew));
05942 
05943               if (optgenerror
05944                   (FLG_INCONDEFS,
05945                    message ("%s %q inconsistently redeclared as %s",
05946                             ekind_capName (old->ukind),
05947                             uentry_getName (unew),
05948                             ekind_unparseLong (unew->ukind)),
05949                    uentry_whereDeclared (unew)))
05950                 {
05951                   uentry_showWhereLast (old);
05952                 }
05953             }
05954         }
05955     }
05956 
05957   uentry_copyInto (old, unew);
05958 }
05959 
05960 /*
05961 ** def is the definition of spec, modifies spec
05962 **
05963 ** reports any inconsistencies
05964 ** returns the summary of all available information
05965 ** if spec and def are inconsistent, def is returned
05966 */
05967 
05968 void
05969 uentry_showWhereLast (uentry spec)
05970 {
05971   if (uentry_isValid (spec))
05972     {
05973       if (fileloc_isDefined (spec->whereDefined)
05974           && !fileloc_isLib (spec->whereDefined)
05975           && !fileloc_isPreproc (spec->whereDefined))
05976         {
05977           llgenindentmsg (message ("Previous definition of %q: %t", 
05978                                    uentry_getName (spec),
05979                                    uentry_getType (spec)),
05980                           uentry_whereDefined (spec));
05981         }
05982       else if (uentry_isDeclared (spec))
05983         {
05984           llgenindentmsg (message ("Previous declaration of %q: %t", 
05985                                    uentry_getName (spec),
05986                                    uentry_getType (spec)),
05987                           uentry_whereDeclared (spec));
05988         }
05989       else if (uentry_isSpecified (spec))
05990         {
05991           if (uentry_hasName (spec))
05992             {
05993               llgenindentmsg (message ("Specification of %q: %t", 
05994                                        uentry_getName (spec),
05995                                        uentry_getType (spec)),
05996                               uentry_whereSpecified (spec));
05997             }
05998           else
05999             {
06000               llgenindentmsg (message ("Specification: %t", uentry_getType (spec)),
06001                               uentry_whereSpecified (spec));
06002             }
06003         }
06004       else
06005         {
06006           /* nothing to show */
06007         }
06008     }
06009 }
06010 
06011 void
06012 uentry_showDefSpecInfo (uentry ce, fileloc fwhere)
06013 {
06014   fileloc loc = uentry_whereDefined (ce);
06015   
06016   if (fileloc_isUser (loc) && !fileloc_equal (loc, fwhere))
06017     {
06018       llgenindentmsg (message ("Definition of %q", uentry_getName (ce)),
06019                       loc);
06020     }
06021 
06022   loc = uentry_whereSpecified (ce);
06023   
06024   if (fileloc_isUser (loc) && !fileloc_equal (loc, fwhere))
06025     {
06026       llgenindentmsg (message ("Specification of %q", uentry_getName (ce)),
06027                       loc);
06028     }
06029 }
06030 
06031 void uentry_showWhereLastExtra (uentry spec, cstring extra)
06032 {
06033   if (uentry_isDeclared (spec))
06034     {
06035       llgenindentmsg (message ("Previous declaration of %q: %q", 
06036                                uentry_getName (spec), extra),
06037                       uentry_whereDeclared (spec));
06038     }
06039   else if (uentry_isSpecified (spec))
06040     {
06041       llgenindentmsg (message ("Specification of %q: %q", 
06042                                uentry_getName (spec), extra),
06043                       uentry_whereSpecified (spec));
06044     }
06045   else
06046     {
06047       cstring_free (extra);
06048     }
06049 }
06050 
06051 void
06052 uentry_showWhereDeclared (uentry spec)
06053 {
06054   if (uentry_isDeclared (spec))
06055     {
06056       if (uentry_hasName (spec))
06057         {
06058           llgenindentmsg (message ("Declaration of %q", uentry_getName (spec)),
06059                           uentry_whereDeclared (spec));
06060         }
06061       else
06062         {
06063           llgenindentmsg (cstring_makeLiteral ("Declaration"), uentry_whereDeclared (spec));
06064         }
06065     }
06066   else if (uentry_isSpecified (spec))
06067     {
06068       if (uentry_hasName (spec))
06069         {
06070           llgenindentmsg (message ("Specification of %q", uentry_getName (spec)),
06071                           uentry_whereSpecified (spec));
06072         }
06073       else
06074         {
06075           llgenindentmsg (cstring_makeLiteral ("Specification"), uentry_whereSpecified (spec));
06076         }
06077     }
06078   else
06079     {
06080       /* nothing to show */
06081     }
06082     
06083 }
06084 
06085 void
06086 uentry_showWhereAny (uentry spec)
06087 {
06088   if (uentry_isDeclared (spec))
06089     {
06090       if (uentry_hasName (spec))
06091         {
06092           llgenindentmsg (message ("Declaration of %q", uentry_getName (spec)),
06093                           uentry_whereDeclared (spec));
06094         }
06095       else
06096         {
06097           llgenindentmsg (cstring_makeLiteral ("Declaration"), uentry_whereDeclared (spec));
06098         }
06099     }
06100   else if (uentry_isSpecified (spec))
06101     {
06102       if (uentry_hasName (spec))
06103         {
06104           llgenindentmsg (message ("Specification of %q",
06105                                    uentry_getName (spec)),
06106                           uentry_whereSpecified (spec));
06107         }
06108       else
06109         {
06110           llgenindentmsg (cstring_makeLiteral ("Specification"), 
06111                           uentry_whereSpecified (spec));
06112         }
06113     }
06114   else if (fileloc_isDefined (uentry_whereDefined (spec))) 
06115     {
06116       if (uentry_hasName (spec))
06117         {
06118           llgenindentmsg (message ("Definition of %q", uentry_getName (spec)),
06119                           uentry_whereDefined (spec));
06120         }
06121       else
06122         {
06123           llgenindentmsg (cstring_makeLiteral ("Definition"), uentry_whereDefined (spec));
06124         }
06125     }
06126   else
06127     {
06128       /* nothing to show */
06129     }
06130 }
06131 
06132 void
06133 uentry_showWhereDefined (uentry spec)
06134 {
06135   if (uentry_isCodeDefined (spec))
06136     {
06137       llgenindentmsg (message ("Previous definition of %q", uentry_getName (spec)),
06138                       uentry_whereDefined (spec));
06139     }
06140 }
06141 
06142 void
06143 uentry_showWhereLastPlain (uentry spec)
06144 {
06145   if (uentry_isDeclared (spec))
06146     {
06147       llgenindentmsg (message ("Previous declaration of %q", uentry_getName (spec)),
06148                       uentry_whereDeclared (spec));
06149     }
06150   else if (uentry_isSpecified (spec))
06151     {
06152       llgenindentmsg (message ("Specification of %q", uentry_getName (spec)),
06153                       uentry_whereSpecified (spec));
06154     }
06155   else
06156     {
06157           }
06158 }
06159 
06160 static void
06161 uentry_showWhereLastVal (uentry spec, cstring val)
06162 {
06163   if (uentry_isDeclared (spec))
06164     {
06165       llgenindentmsg (message ("Previous declaration of %q: %s", 
06166                                uentry_getName (spec), val),
06167                       uentry_whereDeclared (spec));
06168     }
06169   else if (uentry_isSpecified (spec))
06170     {
06171       llgenindentmsg (message ("Specification of %q: %s", 
06172                                uentry_getName (spec), val),
06173                       uentry_whereSpecified (spec));
06174     }
06175   else
06176     {
06177     }
06178 }
06179 
06180 void
06181 uentry_showWhereSpecified (uentry spec)
06182 {
06183   if (uentry_isSpecified (spec))
06184     {
06185       if (uentry_hasName (spec))
06186         {
06187           llgenindentmsg (message ("Specification of %q", uentry_getName (spec)),
06188                           uentry_whereSpecified (spec));
06189         }
06190       else
06191         {
06192           llgenindentmsg (cstring_makeLiteral ("Specification"), 
06193                           uentry_whereSpecified (spec));
06194         }
06195     }
06196   else if (uentry_isDeclared (spec))
06197     {
06198       llgenindentmsg (message ("Declaration of %q", uentry_getName (spec)),
06199                       uentry_whereDeclared (spec));
06200     }
06201   else
06202     {
06203       /* nothing to show */
06204     }
06205 }
06206 
06207 void
06208 uentry_showWhereSpecifiedExtra (uentry spec, cstring s)
06209 {
06210   if (uentry_isSpecified (spec))
06211     {
06212       if (uentry_hasName (spec))
06213         {
06214           llgenindentmsg (message ("Specification of %q: %q", 
06215                                    uentry_getName (spec), s),
06216                           uentry_whereSpecified (spec));
06217         }
06218       else
06219         {
06220           llgenindentmsg (message ("Specification: %q", s), 
06221                           uentry_whereSpecified (spec));
06222         }
06223     }
06224   else if (uentry_isDeclared (spec))
06225     {
06226       llgenindentmsg (message ("Declaration of %q: %q", 
06227                                uentry_getName (spec), s),
06228                       uentry_whereDeclared (spec));
06229     }
06230   else
06231     {
06232       llgenindentmsg (message ("Previous: %q", s),
06233                       uentry_whereLast (spec));
06234     }
06235 }
06236 
06237 /*
06238 **
06239 */
06240 
06241 static void
06242 checkStructConformance (uentry old, uentry unew)
06243 {
06244   ctype oldr, newr; 
06245   uentryList fold, fnew;
06246 
06247   /*
06248   ** requires: types of old and new are structs or unions
06249   */
06250 
06251   llassert (uentry_isValid (old));
06252   llassert (uentry_isValid (unew));
06253 
06254   oldr = ctype_realType (old->utype);
06255   fold =  ctype_getFields (oldr);
06256 
06257   newr = ctype_realType (unew->utype);
06258   fnew = ctype_getFields (newr);
06259 
06260   if (!uentryList_matchFields (fold, fnew))
06261     {
06262       if (fileloc_equal (uentry_whereLast (old),
06263                          uentry_whereLast (unew)))
06264         {
06265           ; /* cheat! */
06266         }
06267       else 
06268         {
06269           if (optgenerror 
06270               (FLG_MATCHFIELDS,
06271                message ("%q %q %rdeclared with fields { %q }, %s "
06272                         "with fields { %q }",
06273                         cstring_makeLiteral (ctype_isStruct (newr) ? "Structure": "Union"),
06274                         uentry_getName (old), 
06275                         uentry_isDeclared (old),
06276                         uentryList_unparseAbbrev (fnew),
06277                         uentry_specOrDefName (old),
06278                         uentryList_unparseAbbrev (fold)),
06279                uentry_whereDeclared (unew)))
06280             {
06281               uentry_showWhereLastPlain (old);
06282               uentryList_showFieldDifference (fold, fnew);
06283             }
06284         }
06285 
06286       old->utype = unew->utype;
06287     }
06288 }
06289 
06290 static void
06291 checkEnumConformance (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew)
06292 {
06293   /*
06294   ** requires old and new are enums
06295   */
06296   
06297   ctype        rold = ctype_realType (old->utype);
06298   ctype        rnew = ctype_realType (unew->utype);
06299   enumNameList eold = ctype_elist (rold);
06300   enumNameList enew = ctype_elist (rnew);
06301   
06302   if (!enumNameList_match (eold, enew))
06303     {
06304       if (optgenerror 
06305           (FLG_MATCHFIELDS,
06306            message ("Enum %q declared with members { %q } but "
06307                     "specified with members { %q }",
06308                     uentry_getName (old), 
06309                     enumNameList_unparse (enew),
06310                     enumNameList_unparse (eold)),
06311            uentry_whereDeclared (unew)))
06312         {
06313           uentry_showWhereSpecified (old);
06314           old->utype = unew->utype;
06315         }
06316     }
06317 }
06318 
06319 /*
06320 ** either oldCurrent or newCurrent may be undefined!
06321 */
06322 
06323 static void
06324 paramTypeError (uentry old, uentry oldCurrent, ctype oldType,
06325                 uentry unew, uentry newCurrent, ctype newType,
06326                 int paramno)
06327 {
06328   bool hasError = FALSE;
06329 
06330   if (uentry_isValid (newCurrent) && uentry_isDeclared (newCurrent))
06331     {
06332       if (uentry_hasName (newCurrent))
06333         {
06334           hasError = optgenerror 
06335             (FLG_TYPE,
06336              message ("Parameter %d, %q, of function %q has inconsistent type: "
06337                       "declared %t, %s %t",
06338                       paramno + 1, uentry_getName (newCurrent), 
06339                       uentry_getName (unew),
06340                       newType, uentry_specOrDefName (old), oldType),
06341              uentry_whereDeclared (newCurrent));
06342         }
06343       else
06344         {
06345           hasError = optgenerror
06346             (FLG_TYPE,
06347              message ("Parameter %d of function %q has inconsistent type: "
06348                       "declared %t, %s %t",
06349                       paramno + 1, uentry_getName (unew),
06350                       newType, uentry_specOrDefName (old), oldType),
06351              uentry_whereDeclared (newCurrent));
06352 
06353           DPRINTF (("type: %s / %s",
06354                     ctype_unparse (newType),
06355                     ctype_unparse (ctype_realType (newType))));
06356         }
06357     }
06358   else 
06359     {
06360       if (uentry_isDeclared (unew))
06361         {
06362           hasError = optgenerror 
06363             (FLG_TYPE,
06364              message ("Parameter %d of function %s has inconsistent type: "
06365                       "declared %t, %s %t",
06366                       paramno + 1, unew->uname, 
06367                       newType, uentry_specOrDefName (old), oldType),
06368              uentry_whereDeclared (unew));
06369         }
06370       else
06371         {
06372           hasError = optgenerror
06373             (FLG_TYPE,
06374              message ("Parameter %d of function %s has inconsistent type: "
06375                       "declared %t, %s %t",
06376                       paramno + 1, unew->uname, 
06377                       newType, uentry_specOrDefName (old), oldType),
06378              uentry_whereDeclared (unew));
06379         }
06380     }
06381   
06382   if (hasError)
06383     {
06384       if (!uentry_isUndefined (oldCurrent))
06385         {
06386           if (!uentry_isUndefined (newCurrent) 
06387               && cstring_equal (uentry_rawName (newCurrent), uentry_rawName (oldCurrent)))
06388             {
06389               uentry_showWhereLast (oldCurrent);
06390             }
06391           else
06392             {
06393               uentry_showWhereLastPlain (old);
06394             }
06395           
06396           uentry_setType (oldCurrent, newType);
06397         }
06398       else
06399         {
06400           uentry_showWhereLastPlain (old);
06401         }
06402     }
06403 }
06404 
06405 static void
06406 nargsError (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew)
06407 {
06408   if (optgenerror 
06409       (FLG_TYPE,
06410        message ("Function %s %rdeclared with %d arg%p, %s with %d",
06411                 unew->uname, 
06412                 uentry_isDeclared (old),
06413                 uentryList_size (uentry_getParams (unew)),
06414                 uentry_specOrDefName (old),
06415                 uentryList_size (uentry_getParams (old))),
06416        uentry_whereDeclared (unew)))
06417     {
06418       uentry_showWhereLastPlain (old);
06419     }
06420 }
06421 
06422 static void
06423 returnValueError (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew)
06424 {
06425   if (optgenerror
06426       (FLG_INCONDEFS,
06427        message ("Function %s inconsistently %rdeclared to return %t",
06428                 unew->uname,
06429                 uentry_isDeclared (old),
06430                 ctype_returnValue (unew->utype)),
06431        uentry_whereDeclared (unew)))
06432     {
06433       uentry_showWhereLastVal (old, ctype_unparse (ctype_returnValue (old->utype)));
06434     }
06435 }
06436 
06437 static cstring paramStorageName (uentry ue)
06438 {
06439   return (cstring_makeLiteralTemp (uentry_isParam (ue) ? "param" : "storage"));
06440 }
06441 
06442 static cstring fcnErrName (uentry ue)
06443 {
06444   return (cstring_makeLiteralTemp (uentry_isFunction (ue) ? "to return" : "as"));
06445 }
06446 
06447 extern /*@observer@*/ cstring uentry_checkedName (uentry ue)
06448 {
06449   if (uentry_isVar (ue))
06450     {
06451       return (checkedName (ue->info->var->checked));
06452     }
06453   else
06454     {
06455       return (cstring_makeLiteralTemp ("<checked invalid>"));
06456     }
06457 }
06458 
06459 static cstring checkedName (chkind checked)
06460 {
06461   switch (checked)
06462     {
06463     case CH_UNKNOWN:       return (cstring_makeLiteralTemp ("unknown"));
06464     case CH_UNCHECKED:     return (cstring_makeLiteralTemp ("unchecked"));
06465     case CH_CHECKED:       return (cstring_makeLiteralTemp ("checked"));
06466     case CH_CHECKMOD:      return (cstring_makeLiteralTemp ("checkmod"));
06467     case CH_CHECKEDSTRICT: return (cstring_makeLiteralTemp ("checkedstrict"));
06468     }
06469   BADEXIT;
06470 }
06471 
06472 static
06473 void checkNullState (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew, bool mustConform, bool completeConform)
06474 {
06475   nstate oldState;
06476   nstate newState;
06477   
06478   if (uentry_isVar (unew))
06479     {
06480       llassert (uentry_isVar (old));
06481       
06482       oldState = old->info->var->nullstate;
06483       newState = unew->info->var->nullstate;
06484     }
06485   else
06486     {
06487       oldState = sRef_getNullState (old->sref);
06488       newState = sRef_getNullState (unew->sref);
06489     }
06490 
06491   if (oldState == NS_ABSNULL)
06492     {
06493       if (uentry_isVar (old))
06494         {
06495           old->info->var->nullstate = newState;
06496         }
06497       
06498       sRef_mergeNullState (old->sref, newState);
06499     }
06500   else if (newState == NS_UNKNOWN)
06501     {
06502       if (completeConform && newState != oldState
06503           && uentry_isReallySpecified (old))
06504         {
06505           if (optgenerror 
06506               (FLG_NEEDSPEC,
06507                message ("%s %q specified as %s, but declared without %s qualifier",
06508                         ekind_capName (unew->ukind),
06509                         uentry_getName (unew),
06510                         nstate_unparse (oldState),
06511                         nstate_unparse (oldState)),
06512                uentry_whereDeclared (unew)))
06513             {
06514               uentry_showWhereSpecified (old);
06515             }
06516         }
06517       
06518       if (uentry_isVar (unew))
06519         {
06520           unew->info->var->nullstate = oldState;
06521         }
06522 
06523       sRef_mergeNullState (unew->sref, oldState);
06524     }
06525   else if (newState == NS_POSNULL)
06526     {
06527       if (oldState == NS_MNOTNULL 
06528           && (ctype_isUA (unew->utype) 
06529               || (uentry_isFunction (unew)
06530                   && ctype_isUA (ctype_returnValue (unew->utype)))))
06531         {
06532           if (uentry_isVar (unew))
06533             {
06534               unew->info->var->nullstate = oldState;
06535             }
06536 
06537           sRef_mergeNullState (unew->sref, oldState);
06538         }
06539       else 
06540         {
06541           if (oldState == NS_NOTNULL || oldState == NS_MNOTNULL 
06542               || oldState == NS_UNKNOWN)
06543             {
06544               if (mustConform)
06545                 {
06546                   if (optgenerror 
06547                       (FLG_INCONDEFS,
06548                        message 
06549                        ("%s %q inconsistently %rdeclared %s possibly null storage, "
06550                         "%s %q qualifier",
06551                         uentry_ekindName (unew),
06552                         uentry_getName (unew),
06553                         uentry_isDeclared (old),
06554                         fcnErrName (unew),
06555                         uentry_specOrDefName (old),
06556                         cstring_makeLiteral (oldState == NS_MNOTNULL ? "with notnull" : "without null")),
06557                        uentry_whereDeclared (unew)))
06558                     {
06559                       uentry_showWhereSpecified (old);
06560                     }
06561                 }
06562             }
06563           
06564           if (uentry_isVar (old))
06565             {
06566               old->info->var->nullstate = newState;
06567             }
06568 
06569           sRef_mergeNullState (old->sref, newState);
06570         }
06571     }
06572   else if (newState == NS_MNOTNULL)
06573     {
06574       if (oldState != NS_MNOTNULL)
06575         {
06576           if (mustConform)
06577             {
06578               if (optgenerror 
06579                   (FLG_INCONDEFS,
06580                    message ("%s %q inconsistently %rdeclared %s notnull storage, "
06581                             "%s without notnull qualifier",
06582                             uentry_ekindName (unew),
06583                             uentry_getName (unew),
06584                             uentry_isDeclared (old),
06585                             fcnErrName (unew),
06586                             uentry_specOrDefName (old)),
06587                    uentry_whereDeclared (unew)))
06588                 {
06589                   uentry_showWhereSpecified (old);
06590                 }
06591             }
06592           
06593           if (uentry_isVar (old))
06594             {
06595               old->info->var->nullstate = newState;
06596             }
06597 
06598           sRef_mergeNullState (old->sref, newState);
06599         }
06600     }
06601   else
06602     {
06603       if (uentry_isVar (unew)) 
06604         {
06605           unew->info->var->nullstate = oldState;
06606         }
06607 
06608       sRef_mergeNullState (unew->sref, oldState);
06609     }
06610 }
06611 
06612 static
06613 void checkDefState (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew, 
06614                     bool mustConform, bool completeConform)
06615 {
06616   sstate oldState;
06617   sstate newState;
06618   bool vars = FALSE;
06619 
06620   if (uentry_isVar (old) && uentry_isVar (unew))
06621     {
06622       oldState = old->info->var->defstate;
06623       newState = unew->info->var->defstate;
06624       vars = TRUE;
06625     }
06626   else
06627     {
06628       oldState = sRef_getDefState (old->sref);
06629       newState = sRef_getDefState (unew->sref);
06630     }
06631 
06632   if (newState != oldState && newState != SS_UNKNOWN && newState != SS_DEFINED)
06633     {
06634       if (mustConform)
06635         {
06636           if (optgenerror 
06637               (FLG_INCONDEFS,
06638                message ("%s %q inconsistently %rdeclared %s %s %s, "
06639                         "%s %s %s %s",
06640                         uentry_ekindName (unew),
06641                         uentry_getName (unew),
06642                         uentry_isDeclared (old),
06643                         fcnErrName (unew),
06644                         sstate_unparse (newState),
06645                         paramStorageName (unew),
06646                         uentry_specOrDefName (old),
06647                         fcnErrName (unew),
06648                         sstate_unparse (oldState),
06649                         paramStorageName (unew)),
06650                uentry_whereDeclared (unew)))
06651             {
06652               uentry_showWhereSpecified (old);
06653             }
06654         }
06655       
06656       if (vars) old->info->var->defstate = newState;
06657       sRef_setDefState (old->sref, newState, uentry_whereDeclared (unew));
06658     }
06659   else
06660     {
06661       if (completeConform
06662           && (newState != oldState) && (oldState != SS_DEFINED)
06663           && uentry_isReallySpecified (old))
06664         {
06665           if (optgenerror 
06666               (FLG_NEEDSPEC,
06667                message ("%s %q specified as %s, but declared without %s qualifier",
06668                         ekind_capName (unew->ukind),
06669                         uentry_getName (unew),
06670                         sstate_unparse (oldState),
06671                         sstate_unparse (oldState)),
06672                uentry_whereDeclared (unew)))
06673             {
06674               uentry_showWhereSpecified (old);
06675             }
06676         }
06677 
06678       if (vars) unew->info->var->defstate = oldState;
06679       sRef_setDefState (unew->sref, oldState, uentry_whereDeclared (unew));
06680     }
06681 }
06682 
06683 static void 
06684   checkAliasState (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew, 
06685                    bool mustConform, bool completeConform)
06686 {
06687   alkind newKind;
06688   alkind oldKind;
06689 
06690   oldKind = sRef_getAliasKind (old->sref);
06691   newKind = sRef_getAliasKind (unew->sref);
06692 
06693   if (alkind_isImplicit (newKind) 
06694       || (alkind_isRefCounted (newKind) && !uentry_isDatatype (unew)))
06695     {
06696       if (completeConform && !alkind_equal (newKind, oldKind)
06697           && uentry_isReallySpecified (old))
06698         {
06699           if (optgenerror 
06700               (FLG_NEEDSPEC,
06701                message ("%s %q specified as %s, but declared without "
06702                         "explicit alias qualifier",
06703                         ekind_capName (unew->ukind),
06704                         uentry_getName (unew),
06705                         alkind_unparse (oldKind)),
06706                uentry_whereDeclared (unew)))
06707             {
06708               uentry_showWhereSpecified (old);
06709             }
06710         }
06711 
06712       /*  
06713       ** This really shouldn't be necessary, but it is!
06714       ** Function params (?) use new here.
06715       */
06716 
06717       sRef_setAliasKind (unew->sref, oldKind, uentry_whereDeclared (unew));
06718       return;
06719     }
06720 
06721   if (alkind_isKnown (newKind))
06722     {
06723       if (!alkind_equal (oldKind, newKind))
06724         {
06725           if (alkind_isKnown (oldKind))
06726             {
06727               if (mustConform && 
06728                   optgenerror 
06729                   (FLG_INCONDEFS,
06730                    message ("%s %q inconsistently %rdeclared %s %s storage, "
06731                             "%s as %s storage",
06732                             uentry_ekindName (unew),
06733                             uentry_getName (unew),
06734                             uentry_isDeclared (old),
06735                             fcnErrName (unew),
06736                             alkind_unparse (newKind),
06737                             uentry_specOrDefName (old),
06738                             alkind_unparse (oldKind)),
06739                    uentry_whereDeclared (unew)))
06740                 {
06741                   uentry_showWhereSpecified (old);
06742 
06743                   sRef_setAliasKind (old->sref, AK_ERROR, 
06744                                      uentry_whereDeclared (unew));
06745                 }
06746               else
06747                 {
06748                   sRef_setAliasKind (old->sref, newKind, 
06749                                      uentry_whereDeclared (unew));
06750                 }
06751             }
06752           else
06753             {
06754               if (!(alkind_isImplicit (newKind)))
06755                 {
06756                   if (mustConform &&
06757                       !uentry_isFunction (unew) &&
06758                       optgenerror 
06759                       (FLG_INCONDEFS,
06760                        message ("%s %q inconsistently %rdeclared %s %s storage, "
06761                                 "implicitly %s as temp storage",
06762                                 uentry_ekindName (unew),
06763                                 uentry_getName (unew),
06764                                 uentry_isDeclared (old),
06765                                 fcnErrName (unew),
06766                                 alkind_unparse (newKind),
06767                                 uentry_specOrDefName (old)),
06768                        uentry_whereDeclared (unew)))
06769                     {
06770                       uentry_showWhereSpecified (old);
06771                       oldKind = AK_ERROR;
06772                     }
06773                   
06774                   sRef_setAliasKind (old->sref, newKind, 
06775                                      uentry_whereDeclared (unew));
06776                 }
06777               else /* newKind is temp or refcounted */
06778                 {
06779                   ;
06780                 }
06781             }
06782         }
06783     }
06784   else /* newKind unknown */
06785     {
06786       ;
06787     }
06788 }
06789 
06790 static void 
06791   checkExpState(/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew, 
06792                 bool mustConform, bool completeConform)
06793 {
06794   exkind newKind;
06795   exkind oldKind;
06796   
06797   oldKind = sRef_getExKind (old->sref);
06798   newKind = sRef_getExKind (unew->sref);
06799 
06800   if (exkind_isKnown (newKind))
06801     {
06802       if (oldKind != newKind)
06803         {
06804           if (exkind_isKnown (oldKind))
06805             {
06806               if (mustConform && 
06807                   optgenerror 
06808                   (FLG_INCONDEFS,
06809                    message ("%s %q inconsistently %rdeclared %s %s, %s as %s",
06810                             uentry_ekindName (unew),
06811                             uentry_getName (unew),
06812                             uentry_isDeclared (old),
06813                             fcnErrName (unew),
06814                             exkind_unparse (newKind),
06815                             uentry_specOrDefName (old),
06816                             exkind_unparse (oldKind)),
06817                    uentry_whereDeclared (unew)))
06818                 {
06819                   uentry_showWhereSpecified (old);
06820                 }
06821 
06822               sRef_setExKind (old->sref, newKind, uentry_whereDefined (unew));
06823             }
06824           else
06825             {
06826               if (mustConform &&
06827                   optgenerror 
06828                   (FLG_INCONDEFS,
06829                    message ("%s %q inconsistently %rdeclared %s %s, "
06830                             "implicitly %s without exposure qualifier",
06831                             uentry_ekindName (unew),
06832                             uentry_getName (unew),
06833                             uentry_isDeclared (old),
06834                             fcnErrName (unew),
06835                             exkind_unparse (newKind),
06836                             uentry_specOrDefName (old)),
06837                    uentry_whereDeclared (unew)))
06838                 {
06839                   uentry_showWhereSpecified (old);
06840                 }
06841 
06842               sRef_setExKind (old->sref, newKind, uentry_whereDefined (unew));
06843             }
06844         }
06845     }
06846   else
06847     {
06848       if (completeConform && exkind_isKnown (oldKind)
06849           && uentry_isReallySpecified (old))
06850         {
06851           if (optgenerror 
06852               (FLG_NEEDSPEC,
06853                message ("%s %q specified as %s, but declared without "
06854                         "exposure qualifier",
06855                         ekind_capName (unew->ukind),
06856                         uentry_getName (unew),
06857                         exkind_unparse (oldKind)),
06858                uentry_whereDeclared (unew)))
06859             {
06860               uentry_showWhereSpecified (old);
06861             }
06862         }
06863 
06864       /* yes, this is necessary! (if its a param) */
06865       sRef_setExKind (unew->sref, oldKind, fileloc_undefined);
06866     }
06867 }
06868 
06869 static void
06870 uentry_checkStateConformance (/*@notnull@*/ uentry old,
06871                               /*@notnull@*/ uentry unew,
06872                               bool mustConform, bool completeConform)
06873 {
06874   checkDefState (old, unew, mustConform, completeConform);
06875   checkNullState (old, unew, mustConform, completeConform);
06876   checkAliasState (old, unew, mustConform, completeConform);
06877   checkExpState (old, unew, mustConform, completeConform);
06878 
06879   sRef_storeState (old->sref);
06880   sRef_storeState (unew->sref);
06881 }
06882 
06883 static void
06884 checkVarConformance (uentry old, uentry unew, bool mustConform, bool completeConform)
06885 {
06886   if (uentry_isElipsisMarker (old) || uentry_isElipsisMarker (unew))
06887     {
06888       return;
06889     }
06890 
06891   llassert (uentry_isVar (old));
06892   llassert (uentry_isVar (unew));
06893 
06894   if (cstring_isEmpty (old->uname)) 
06895     {
06896       cstring_free (old->uname);
06897       old->uname = cstring_copy (unew->uname);
06898     }
06899 
06900   if (unew->info->var->kind == VKRETPARAM
06901       || unew->info->var->kind == VKSEFRETPARAM)
06902     {
06903       if (old->info->var->kind != VKRETPARAM
06904           && old->info->var->kind != VKSEFRETPARAM)
06905         {
06906           if (optgenerror 
06907               (FLG_INCONDEFS,
06908                message ("Parameter %q inconsistently %rdeclared as "
06909                         "returned parameter",
06910                         uentry_getName (unew),
06911                         uentry_isDeclared (old)),
06912                uentry_whereDeclared (unew)))
06913             {
06914               uentry_showWhereSpecified (old);
06915               old->info->var->kind = unew->info->var->kind;
06916             }
06917         }
06918     }
06919 
06920 
06921   if (unew->info->var->kind == VKSEFPARAM || unew->info->var->kind == VKSEFRETPARAM)
06922     {
06923       if (old->info->var->kind != VKSEFPARAM 
06924           && old->info->var->kind != VKSEFRETPARAM)
06925         {
06926           if (optgenerror 
06927               (FLG_INCONDEFS,
06928                message ("Parameter %qinconsistently %rdeclared as "
06929                         "sef parameter",
06930                         uentry_getOptName (unew),
06931                         uentry_isDeclared (old)),
06932                uentry_whereDeclared (unew)))
06933             {
06934               uentry_showWhereSpecified (old);
06935               old->info->var->kind = unew->info->var->kind;
06936             }
06937         }
06938     }
06939 
06940   if (old->info->var->kind == VKSPEC)
06941     {
06942       old->info->var->kind = unew->info->var->kind;
06943     }
06944   else
06945     {
06946       unew->info->var->kind = old->info->var->kind;
06947     }
06948 
06949   if (unew->info->var->checked != CH_UNKNOWN
06950       && unew->info->var->checked != old->info->var->checked)
06951     {
06952       if (old->info->var->checked == CH_UNKNOWN
06953           && !fileloc_isUser (uentry_whereLast (old)))
06954         {
06955           ; /* no error */
06956         }
06957       else
06958         {
06959           if (optgenerror 
06960               (FLG_INCONDEFS,
06961                message ("Variable %q inconsistently %rdeclared as "
06962                         "%s parameter (was %s)",
06963                         uentry_getName (unew),
06964                         uentry_isDeclared (old),
06965                         checkedName (unew->info->var->checked),
06966                         checkedName (old->info->var->checked)),
06967                uentry_whereDeclared (unew)))
06968             {
06969               uentry_showWhereSpecified (old);
06970             }
06971         }
06972       
06973       old->info->var->checked = unew->info->var->checked;
06974     }
06975   else
06976     {
06977       if (completeConform 
06978           && (old->info->var->checked != CH_UNKNOWN)
06979           && uentry_isReallySpecified (old))
06980         {
06981           if (optgenerror 
06982               (FLG_NEEDSPEC,
06983                message ("%s %q specified as %s, but declared without %s qualifier",
06984                         ekind_capName (unew->ukind),
06985                         uentry_getName (unew),
06986                         checkedName (old->info->var->checked),
06987                         checkedName (old->info->var->checked)),
06988                uentry_whereDeclared (unew)))
06989             {
06990               uentry_showWhereSpecified (old);
06991             }
06992         }
06993       
06994       unew->info->var->checked = old->info->var->checked;
06995     }
06996 
06997   uentry_checkStateConformance (old, unew, mustConform, completeConform);
06998 }
06999 
07000 void uentry_checkMatchParam (uentry u1, uentry u2, int paramno, exprNode e)
07001 {
07002   if (uentry_isElipsisMarker (u1) || uentry_isElipsisMarker (u2))
07003     {
07004       return;
07005     }
07006 
07007   llassert (uentry_isVar (u1));
07008   llassert (uentry_isVar (u2));
07009 
07010   if (u1->info->var->kind != u2->info->var->kind) {
07011     if (u1->info->var->kind == VKSEFRETPARAM) {
07012       if (u2->info->var->kind == VKRETPARAM) {
07013         voptgenerror 
07014           (FLG_TYPE,
07015            message ("Function types are inconsistent. Parameter %d is "
07016                     "sef parameter, but non-sef parameter in "
07017                     "assigned function: %s",
07018                     paramno, exprNode_unparse (e)),
07019            exprNode_loc (e));
07020       } else if (u2->info->var->kind == VKSEFPARAM) {
07021         voptgenerror 
07022           (FLG_TYPE,
07023            message ("Function types are inconsistent. Parameter %d is "
07024                     "returns parameter, but non-returns parameter in "
07025                     "assigned function: %s",
07026                     paramno, exprNode_unparse (e)),
07027            exprNode_loc (e));
07028       } else {
07029         voptgenerror 
07030           (FLG_TYPE,
07031            message ("Function types are inconsistent. Parameter %d is "
07032                     "sef returns parameter, but non-sef returns parameter in "
07033                     "assigned function: %s",
07034                     paramno, exprNode_unparse (e)),
07035            exprNode_loc (e));
07036       }
07037     } else if (u1->info->var->kind == VKRETPARAM) {
07038       voptgenerror 
07039         (FLG_TYPE,
07040          message ("Function types are inconsistent. Parameter %d is "
07041                   "returns parameter, but non-returns parameter in "
07042                   "assigned function: %s",
07043                   paramno, exprNode_unparse (e)),
07044          exprNode_loc (e));
07045     } else if (u1->info->var->kind == VKSEFPARAM) {
07046       voptgenerror 
07047         (FLG_TYPE,
07048          message ("Function types are inconsistent. Parameter %d is "
07049                   "sef parameter, but non-sef parameter in "
07050                   "assigned function: %s",
07051                   paramno, exprNode_unparse (e)),
07052          exprNode_loc (e));
07053     } else {
07054       if (u2->info->var->kind == VKSEFRETPARAM) {
07055         voptgenerror 
07056           (FLG_TYPE,
07057            message ("Function types are inconsistent. Parameter %d is "
07058                     "normal parameter, but sef returns parameter in "
07059                     "assigned function: %s",
07060                     paramno, exprNode_unparse (e)),
07061            exprNode_loc (e));
07062       } else if (u2->info->var->kind == VKSEFPARAM) {
07063         voptgenerror 
07064           (FLG_TYPE,
07065            message ("Function types are inconsistent. Parameter %d is "
07066                     "normal parameter, but sef parameter in "
07067                     "assigned function: %s",
07068                     paramno, exprNode_unparse (e)),
07069            exprNode_loc (e));
07070       } else if (u2->info->var->kind == VKRETPARAM) {
07071         voptgenerror 
07072           (FLG_TYPE,
07073            message ("Function types are inconsistent. Parameter %d is "
07074                     "normal parameter, but returns parameter in "
07075                     "assigned function: %s",
07076                     paramno, exprNode_unparse (e)),
07077            exprNode_loc (e));
07078       } else {
07079         BADBRANCH;
07080       }
07081     }
07082   }
07083 
07084   if (u1->info->var->defstate != u2->info->var->defstate) 
07085     {
07086       voptgenerror 
07087         (FLG_TYPE,
07088          message ("Function types are inconsistent. Parameter %d is "
07089                   "%s, but %s in assigned function: %s",
07090                   paramno, 
07091                   sstate_unparse (u1->info->var->defstate),
07092                   sstate_unparse (u2->info->var->defstate),
07093                   exprNode_unparse (e)),
07094          exprNode_loc (e));
07095     }
07096 
07097   if (u1->info->var->nullstate != u2->info->var->nullstate) 
07098     {
07099       voptgenerror 
07100         (FLG_TYPE,
07101          message ("Function types are inconsistent. Parameter %d is "
07102                   "%s, but %s in assigned function: %s",
07103                   paramno, 
07104                   nstate_unparse (u1->info->var->nullstate),
07105                   nstate_unparse (u2->info->var->nullstate),
07106                   exprNode_unparse (e)),
07107          exprNode_loc (e));
07108     }
07109       
07110   if (sRef_getAliasKind (u1->sref) != sRef_getAliasKind (u2->sref))
07111     {
07112       voptgenerror 
07113         (FLG_TYPE,
07114          message ("Function types are inconsistent. Parameter %d is "
07115                   "%s, but %s in assigned function: %s",
07116                   paramno, 
07117                   alkind_unparse (sRef_getAliasKind (u1->sref)),
07118                   alkind_unparse (sRef_getAliasKind (u2->sref)),
07119                   exprNode_unparse (e)),
07120          exprNode_loc (e));
07121     }
07122 
07123   if (sRef_getExKind (u1->sref) != sRef_getExKind (u2->sref))
07124     {
07125       voptgenerror 
07126         (FLG_TYPE,
07127          message ("Function types are inconsistent. Parameter %d is "
07128                   "%s, but %s in assigned function: %s",
07129                   paramno, 
07130                   exkind_unparse (sRef_getExKind (u1->sref)),
07131                   exkind_unparse (sRef_getExKind (u2->sref)),
07132                   exprNode_unparse (e)),
07133          exprNode_loc (e));
07134     }
07135 }
07136 
07137 static void
07138 checkFunctionConformance (/*@unique@*/ /*@notnull@*/ uentry old,
07139                           /*@notnull@*/ uentry unew, 
07140                           bool mustConform, /*@unused@*/ bool completeConform)
07141 {
07142   uentryList oldParams  = uentry_getParams (old);
07143   uentryList newParams  = uentry_getParams (unew);
07144   ctype      newType    = unew->utype;
07145   ctype      oldType    = old->utype;
07146   ctype      oldRetType = ctype_unknown;
07147   ctype      newRetType = ctype_unknown;
07148 
07149   if (uentry_isForward (old))
07150     {
07151       mustConform = FALSE;
07152       uentry_copyInto (old, unew);
07153       return;
07154     }
07155 
07156   /*
07157   ** check return values
07158   */
07159   
07160   if (ctype_isKnown (oldType))
07161     {
07162       llassert (ctype_isFunction (oldType));
07163 
07164       oldRetType = ctype_returnValue (oldType);
07165     }
07166 
07167   if (ctype_isKnown (newType))
07168     {
07169       llassert (ctype_isFunction (newType));
07170 
07171       newRetType = ctype_returnValue (newType);
07172     }
07173 
07174   if (ctype_isKnown (oldRetType) && ctype_isKnown (newRetType)
07175       && !ctype_matchDef (newRetType, oldRetType))
07176     {
07177       if (mustConform) returnValueError (old, unew);
07178     }
07179   else 
07180     {
07181       if (ctype_isConj (newRetType))
07182         {
07183           if (ctype_isConj (oldRetType))
07184             {
07185               if (!ctype_sameAltTypes (newRetType, oldRetType))
07186                 {
07187                   if (optgenerror 
07188                       (FLG_INCONDEFS,
07189                        message ("Function %q inconsistently %rdeclared to "
07190                                 "return alternate types %s "
07191                                 "(types match, but alternates are not identical, "
07192                                 "so checking may not be correct)",
07193                                 uentry_getName (unew),
07194                                 uentry_isDeclared (old),
07195                                 ctype_unparse (newRetType)),
07196                        uentry_whereDeclared (unew)))
07197                     {
07198                       uentry_showWhereLastVal (old, ctype_unparse (oldRetType));
07199                     }
07200                 }
07201             }
07202           else
07203             {
07204               old->utype = ctype_makeFunction (oldRetType, uentryList_copy (newParams));
07205             }
07206         }
07207     }
07208 
07209   uentry_checkStateConformance (old, unew, mustConform, completeConform);
07210 
07211   if (!exitkind_equal (unew->info->fcn->exitCode, old->info->fcn->exitCode))
07212     {
07213       if (exitkind_isKnown (unew->info->fcn->exitCode))
07214         {
07215           if (optgenerror 
07216               (FLG_INCONDEFS,
07217                message ("Function %q inconsistently %rdeclared using %s",
07218                         uentry_getName (unew),
07219                         uentry_isDeclared (old),
07220                         exitkind_unparse (unew->info->fcn->exitCode)),
07221                uentry_whereDeclared (unew)))
07222             {
07223               uentry_showWhereSpecified (old);
07224             }
07225         }
07226       else
07227         {
07228           unew->info->fcn->exitCode = old->info->fcn->exitCode;
07229         }
07230     }
07231 
07232   if (!qual_isUnknown (unew->info->fcn->nullPred))
07233     {
07234       if (!qual_equal (old->info->fcn->nullPred, unew->info->fcn->nullPred))
07235         {
07236           if (optgenerror
07237               (FLG_INCONDEFS,
07238                message ("Function %q inconsistently %rdeclared using %s",
07239                         uentry_getName (unew),
07240                         uentry_isDeclared (old),
07241                         qual_unparse (unew->info->fcn->nullPred)),
07242                uentry_whereDeclared (unew)))
07243             {
07244               uentry_showWhereSpecified (old);
07245             }
07246         }
07247     }
07248   else
07249     {
07250       unew->info->fcn->nullPred = old->info->fcn->nullPred;
07251     }
07252 
07253   if (unew->info->fcn->specialCode != SPC_NONE)
07254     {
07255       if (old->info->fcn->specialCode != unew->info->fcn->specialCode)
07256         {
07257           if (optgenerror
07258               (FLG_INCONDEFS,
07259                message ("Function %q inconsistently %rdeclared using %s",
07260                         uentry_getName (unew),
07261                         uentry_isDeclared (old),
07262                         specCode_unparse (unew->info->fcn->specialCode)),
07263                uentry_whereDeclared (unew)))
07264             {
07265               uentry_showWhereSpecified (old);
07266             }
07267         }
07268     }
07269   else
07270     {
07271       unew->info->fcn->specialCode = old->info->fcn->specialCode;
07272     }
07273           
07274   /*
07275   ** check parameters
07276   */
07277   
07278   if (!uentryList_sameObject (oldParams, newParams)
07279       && (!uentryList_isMissingParams (oldParams)))
07280     {
07281       if (!uentryList_isMissingParams (newParams))
07282         {
07283           int paramno = 0;
07284           int nparams = uentryList_size (oldParams);
07285           bool checknames = context_maybeSet (FLG_DECLPARAMMATCH);
07286 
07287           if (nparams != uentryList_size (newParams))
07288             {
07289               nargsError (old, unew);
07290             }
07291           
07292           if (uentryList_size (newParams) < nparams) 
07293             {
07294               nparams = uentryList_size (newParams);
07295             }
07296 
07297           while (paramno < nparams)
07298             {
07299               uentry oldCurrent = uentryList_getN (oldParams, paramno);
07300               uentry newCurrent  = uentryList_getN (newParams, paramno);
07301               ctype  oldCurrentType = uentry_getType (oldCurrent);
07302               ctype  newCurrentType = uentry_getType (newCurrent);
07303 
07304               llassert (uentry_isValid (oldCurrent)
07305                         && uentry_isValid (newCurrent));
07306               
07307               if (!uentry_isElipsisMarker (oldCurrent)
07308                   && !uentry_isElipsisMarker (newCurrent))
07309                 {
07310                   checkVarConformance (oldCurrent, newCurrent, 
07311                                        mustConform, completeConform);
07312                 }
07313 
07314               if (checknames)
07315                 {
07316                   if (uentry_hasName (oldCurrent) 
07317                       && uentry_hasName (newCurrent))
07318                     {
07319                       cstring oldname = uentry_getName (oldCurrent);
07320                       cstring pfx = context_getString (FLG_DECLPARAMPREFIX);
07321                       cstring oname;
07322                       cstring nname = uentry_getName (newCurrent);
07323                       cstring nnamefix;
07324 
07325                       if (cstring_isDefined (pfx)
07326                           && cstring_equalPrefix (oldname, cstring_toCharsSafe (pfx)))
07327                         {
07328                           oname = cstring_suffix (oldname, cstring_length (pfx));
07329                         }
07330                       else
07331                         {
07332                           oname = oldname;
07333                         /*@-branchstate@*/ } /*@=branchstate@*/
07334 
07335                       if (cstring_isDefined (pfx)
07336                           && cstring_equalPrefix (nname, cstring_toCharsSafe (pfx)))
07337                         {
07338                           nnamefix = cstring_suffix (nname, cstring_length (pfx));
07339                         }
07340                       else
07341                         {
07342                           nnamefix = nname;
07343                         /*@-branchstate@*/ } /*@=branchstate@*/
07344 
07345                       if (!cstring_equal (oname, nnamefix))
07346                         {
07347                           if (optgenerror
07348                               (FLG_DECLPARAMMATCH, 
07349                                message ("Definition parameter name %s does not match "
07350                                         "name of corresponding parameter in "
07351                                         "declaration: %s",
07352                                         nnamefix, oname),
07353                                uentry_whereLast (newCurrent)))
07354                             {
07355                               uentry_showWhereLastPlain (oldCurrent);
07356                             }
07357                         }
07358                       
07359                       cstring_free (oldname);
07360                       cstring_free (nname);
07361                     }
07362                 }
07363 
07364               if (!ctype_match (oldCurrentType, newCurrentType))
07365                 {
07366                   paramTypeError (old, oldCurrent, oldCurrentType,
07367                                   unew, newCurrent, newCurrentType, paramno);
07368                 }
07369               else
07370                 {
07371                   if (ctype_isMissingParamsMarker (newCurrentType)
07372                       || ctype_isElips (newCurrentType)
07373                       || ctype_isMissingParamsMarker (oldCurrentType)
07374                       || ctype_isElips (oldCurrentType))
07375                     {
07376                       ;
07377                     }
07378                   else
07379                     {
07380                       if (ctype_isConj (newCurrentType))
07381                         {
07382                           if (ctype_isConj (oldCurrentType))
07383                             {
07384                               if (!ctype_sameAltTypes (newCurrentType, oldCurrentType))
07385                                 {
07386                                   if (optgenerror 
07387                                       (FLG_INCONDEFS,
07388                                        message ("Parameter %q inconsistently %rdeclared with "
07389                                                 "alternate types %s "
07390                                                 "(types match, but alternates are not identical, "
07391                                                 "so checking may not be correct)",
07392                                                 uentry_getName (newCurrent),
07393                                                 uentry_isDeclared (oldCurrent),
07394                                                 ctype_unparse (newCurrentType)),
07395                                        uentry_whereDeclared (unew)))
07396                                     {
07397                                       uentry_showWhereLastVal (oldCurrent,
07398                                                                ctype_unparse (oldCurrentType));
07399                                     }
07400                                 }
07401                             }
07402                           else
07403                             {
07404                               if (optgenerror 
07405                                   (FLG_INCONDEFS,
07406                                    message ("Parameter %q inconsistently %rdeclared with "
07407                                             "alternate types %s",
07408                                             uentry_getName (newCurrent),
07409                                             uentry_isDeclared (oldCurrent),
07410                                             ctype_unparse (newCurrentType)),
07411                                    uentry_whereDeclared (unew)))
07412                                 {
07413                                   uentry_showWhereLastVal (oldCurrent,
07414                                                            ctype_unparse (oldCurrentType));
07415                                   
07416                                 }
07417                             }
07418                         }
07419                       else 
07420                         {
07421                           if (ctype_isConj (oldCurrentType))
07422                             {
07423                               uentry_setType (newCurrent, oldCurrentType);
07424                             }
07425                         }
07426                     }
07427                 }
07428 
07429               paramno++;  
07430               /*
07431                ** Forgot this!  detected by lclint:
07432                ** uentry.c:1257,15: Suspected infinite loop
07433                */
07434             }
07435         }
07436     }
07437 
07438   if (!uentryList_isMissingParams (newParams))
07439     {
07440       if (ctype_isConj (oldRetType))
07441         {
07442           old->utype = ctype_makeFunction (oldRetType, 
07443                                            uentryList_copy (newParams));
07444         }
07445       else
07446         {
07447           old->utype = unew->utype;
07448         }
07449     }
07450 
07451   checkGlobalsConformance (old, unew, mustConform, completeConform);
07452   checkModifiesConformance (old, unew, mustConform, completeConform);
07453 
07454   if (specialClauses_isDefined (unew->info->fcn->specclauses))
07455     {
07456       if (!specialClauses_isDefined (old->info->fcn->specclauses))
07457         {
07458           if (optgenerror
07459               (FLG_INCONDEFS,
07460                message ("Function %q redeclared using special clauses (can only "
07461                         "be used in first declaration)",
07462                         uentry_getName (unew)),
07463                uentry_whereDeclared (unew)))
07464             {
07465               uentry_showWhereLast (old);
07466             }
07467         }
07468       else
07469         {
07470           specialClauses_checkEqual (old, unew);
07471         }
07472     }
07473 
07474   if (fileloc_isUndefined (old->whereDeclared))
07475     {
07476       old->whereDeclared = fileloc_copy (unew->whereDeclared);
07477     }
07478   else if (fileloc_isUndefined (unew->whereDeclared))
07479     {
07480       unew->whereDeclared = fileloc_copy (old->whereDeclared);
07481     }
07482   else
07483     {
07484       /* no change */
07485     }
07486 }
07487 
07488 void
07489 uentry_mergeConstantValue (uentry ue, /*@only@*/ multiVal m)
07490 {
07491   multiVal uval;
07492 
07493   llassert (uentry_isValid (ue));
07494   llassert (uentry_isEitherConstant (ue));
07495 
07496   uval = ue->info->uconst->val;
07497 
07498   if (multiVal_isDefined (uval))
07499     {
07500       if (multiVal_isDefined (m))
07501         {
07502           if (!multiVal_equiv (uval, m))
07503             {
07504               if (optgenerror 
07505                   (FLG_INCONDEFS,
07506                    message ("%s %q defined with inconsistent value: %q",
07507                             ekind_capName (ue->ukind),
07508                             uentry_getName (ue), 
07509                             multiVal_unparse (m)),
07510                    g_currentloc))
07511                 {
07512                   uentry_showWhereLastExtra (ue, multiVal_unparse (uval));
07513                 }
07514             }
07515         }
07516       multiVal_free (m);
07517     }
07518   else
07519     {
07520       ue->info->uconst->val = m;
07521       multiVal_free (uval);
07522     }
07523 }
07524 
07525 static
07526 bool checkTypeConformance (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew, 
07527                            bool mustConform)
07528 {
07529   bool typeError = FALSE;
07530 
07531   if (uentry_isStructTag (old) || uentry_isUnionTag (old))
07532     {
07533       if (ctype_isSU (old->utype) && ctype_isSU (unew->utype))
07534         {
07535           if (mustConform)
07536             {
07537               checkStructConformance (old, unew); 
07538             }
07539         }
07540       else
07541         {
07542           if (!(ctype_isBogus (old->utype) || ctype_isBogus (unew->utype)))
07543             {
07544               llbug (message ("struct tags: bad types: %t / %t", 
07545                               old->utype, unew->utype));
07546             }
07547         }
07548     }
07549   else if (uentry_isEnumTag (old))
07550     {
07551       if (ctype_isEnum (old->utype) && ctype_isEnum (unew->utype))
07552         {
07553           if (mustConform) checkEnumConformance (old, unew);
07554         }
07555       else 
07556         {
07557           if (!(ctype_isBogus (old->utype) || ctype_isBogus (unew->utype)))
07558             {
07559               llbug (message ("enum! bad type: %s / %s", ctype_unparse (old->utype),
07560                               ctype_unparse (unew->utype)));
07561             }
07562         }
07563     }
07564   else if (!ctype_match (old->utype, unew->utype))
07565     {
07566       if (cstring_equal (uentry_rawName (old), context_getBoolName ()))
07567         {
07568           ctype realt = ctype_realType (unew->utype);
07569           
07570           if (ctype_isRealInt (realt) || ctype_isChar (realt))
07571             {
07572               unew->utype = ctype_bool;
07573             }
07574           else
07575             {
07576               if (mustConform)
07577                 {
07578                   typeError = optgenerror
07579                     (FLG_INCONDEFS,
07580                      message ("%q defined as %s", uentry_getName (old), 
07581                               ctype_unparse (realt)),
07582                      uentry_whereDeclared (unew));
07583                 }
07584             }
07585         } 
07586       else 
07587         {
07588           if (mustConform)
07589             {
07590               ctype oldr = ctype_realType (old->utype);
07591               ctype newr = ctype_realType (unew->utype);
07592               
07593               if (ctype_isStruct (oldr) && ctype_isStruct (newr))
07594                 {
07595                   checkStructConformance (old, unew);
07596                 }
07597               else if (ctype_isUnion (oldr) && ctype_isUnion (newr))
07598                 {
07599                   checkStructConformance (old, unew);
07600                 }
07601               else if (ctype_isEnum (oldr) && ctype_isEnum (newr))
07602                 {
07603                   checkEnumConformance (old, unew);
07604                 }
07605               else if (uentry_isConstant (old) 
07606                        && (ctype_isAbstract (oldr) && ctype_isEnum (newr)))
07607                 {
07608                   /* okay...for now! (should check the type is reset later... */
07609                 }
07610               else
07611                 {
07612                   if (optgenerror 
07613                       (FLG_INCONDEFS,
07614                        message ("%s %q %rdeclared with inconsistent type: %t",
07615                                 ekind_capName (unew->ukind),
07616                                 uentry_getName (unew), 
07617                                 uentry_isDeclared (old),
07618                                 unew->utype),
07619                        uentry_whereDeclared (unew)))
07620                     {
07621                       uentry_showWhereLast (old);
07622                       typeError = TRUE;
07623                     }
07624                 }
07625             }
07626         }
07627     }
07628   else
07629     {
07630       /* no error */
07631     }
07632 
07633   return typeError;
07634 }
07635 
07636 static void
07637 uentry_checkDatatypeConformance (/*@notnull@*/ uentry old,
07638                                  /*@notnull@*/ uentry unew,
07639                                  bool mustConform, bool completeConform)
07640 {
07641   if (ctype_isDefined (unew->info->datatype->type))
07642     {
07643       /*
07644       ** bool is hard coded here, since it is built into LCL.
07645       ** For now, we're stuck with LCL's types.
07646       */
07647 
07648       if (ctype_isDirectBool (old->utype) &&
07649           cstring_equalLit (unew->uname, "bool"))
07650         {
07651           /* if (!context_getFlag (FLG_ABSTRACTBOOL))
07652              evs 2000-07-25: removed
07653           */
07654               unew->utype = ctype_bool;
07655         }
07656       
07657       if (ctype_isUnknown (old->info->datatype->type))
07658         {
07659           old->info->datatype->type = unew->info->datatype->type;
07660         }
07661       else
07662         {
07663           if (ctype_matchDef (old->info->datatype->type,
07664                               unew->info->datatype->type))
07665             {
07666               ;
07667             }
07668           else
07669             {
07670               if (optgenerror 
07671                   (FLG_INCONDEFS,
07672                    message
07673                    ("Type %q %s with inconsistent type: %t",
07674                     uentry_getName (unew), 
07675                     uentry_reDefDecl (old, unew),
07676                     unew->info->datatype->type),
07677                    uentry_whereDeclared (unew)))
07678                 {
07679                   uentry_showWhereLastExtra 
07680                     (old, cstring_copy (ctype_unparse (old->info->datatype->type)));
07681                 }
07682 
07683               old->info->datatype->type = unew->info->datatype->type;
07684             }
07685         }
07686     }
07687   
07688   if (unew->info->datatype->abs != MAYBE)
07689     {
07690       if (ynm_isOff (old->info->datatype->abs)
07691           && ynm_isOn (unew->info->datatype->abs))
07692         {
07693           if (!ctype_isDirectBool (old->utype))
07694             {
07695               if (optgenerror 
07696                   (FLG_INCONDEFS,
07697                    message 
07698                    ("Datatype %q inconsistently %rdeclared as abstract type",
07699                     uentry_getName (unew), 
07700                     uentry_isDeclared (old)),
07701                    uentry_whereDeclared (unew)))
07702                 {
07703                   uentry_showWhereLastPlain (old);
07704                 }
07705             }
07706         }
07707       else if (ynm_isOn (old->info->datatype->abs)
07708                && ynm_isOff (unew->info->datatype->abs))
07709         {
07710           if (!ctype_isDirectBool (old->utype))
07711             {
07712               if (optgenerror 
07713                   (FLG_INCONDEFS,
07714                    message 
07715                    ("Datatype %q inconsistently %rdeclared as concrete type",
07716                     uentry_getName (unew), 
07717                     uentry_isDeclared (old)),
07718                    uentry_whereDeclared (unew)))
07719                 {
07720                   uentry_showWhereLastPlain (old);
07721                 }
07722             }
07723         }
07724       else
07725         {
07726           ;
07727         }
07728     }
07729   else 
07730     {
07731       if (ynm_isOn (old->info->datatype->abs))
07732         {
07733           old->sref = unew->sref;
07734           unew->info->datatype->mut = old->info->datatype->mut;
07735           
07736           if (completeConform
07737               && uentry_isReallySpecified (old))
07738             {
07739               if (optgenerror 
07740                   (FLG_NEEDSPEC,
07741                    message 
07742                    ("Datatype %q specified as abstract, "
07743                     "but abstract annotation not used in declaration",
07744                     uentry_getName (unew)), 
07745                    uentry_whereDeclared (unew)))
07746                 {
07747                   uentry_showWhereLastPlain (old);
07748                 }
07749             }
07750         }
07751     }
07752   
07753   unew->info->datatype->abs = old->info->datatype->abs;   
07754   
07755   if (ynm_isMaybe (unew->info->datatype->mut))
07756     {
07757       if (completeConform && ynm_isOff (old->info->datatype->mut)
07758           && uentry_isReallySpecified (old))
07759         {
07760           if (optgenerror 
07761               (FLG_NEEDSPEC,
07762                message 
07763                ("Datatype %q specified as immutable, "
07764                 "but immutable annotation not used in declaration",
07765                 uentry_getName (unew)), 
07766                uentry_whereDeclared (unew)))
07767             {
07768               uentry_showWhereLastPlain (old);
07769             }
07770         }
07771       
07772       unew->info->datatype->mut = old->info->datatype->mut;
07773     }
07774   else if (ynm_isMaybe (old->info->datatype->mut))
07775     {
07776       old->info->datatype->mut = unew->info->datatype->mut;
07777     }
07778   else
07779     {
07780       if (ynm_isOn (old->info->datatype->abs))
07781         {
07782           if (ynm_isOn (old->info->datatype->mut) && ynm_isOff (unew->info->datatype->mut))
07783             {
07784               if (optgenerror
07785                   (FLG_INCONDEFS,
07786                    message ("Datatype %q inconsistently %rdeclared as immutable",
07787                             uentry_getName (unew), 
07788                             uentry_isDeclared (old)),
07789                    uentry_whereDeclared (unew)))
07790                 {
07791                   uentry_showWhereLastPlain (old);
07792                 }
07793             }
07794           else 
07795             {
07796               if (ynm_isOff (old->info->datatype->mut)
07797                   && ynm_isOn (unew->info->datatype->mut))
07798                 {
07799                   if (optgenerror
07800                       (FLG_INCONDEFS,
07801                        message ("Datatype %q inconsistently %rdeclared as mutable",
07802                                 uentry_getName (unew), 
07803                                 uentry_isDeclared (old)),
07804                        uentry_whereDeclared (unew)))
07805                     {
07806                       uentry_showWhereLastPlain (old);
07807                     }
07808                 }
07809             }
07810         }
07811       old->info->datatype->mut = unew->info->datatype->mut;       
07812     }
07813 
07814   uentry_checkStateConformance (old, unew, mustConform, completeConform);
07815 }
07816 
07817 static void
07818 uentry_checkConstantConformance (/*@notnull@*/ uentry old,
07819                                  /*@notnull@*/ uentry unew,
07820                                  bool mustConform, 
07821                                  /*@unused@*/ bool completeConform)
07822 {
07823   multiVal oldVal = old->info->uconst->val;
07824   multiVal newVal = unew->info->uconst->val;
07825   
07826   if (multiVal_isDefined (oldVal))
07827     {
07828       if (multiVal_isDefined (newVal))
07829         {
07830           if (!multiVal_equiv (oldVal, newVal))
07831             {
07832               if (mustConform
07833                   && optgenerror 
07834                   (FLG_INCONDEFS,
07835                    message ("%s %q %rdeclared with inconsistent value: %q",
07836                             ekind_capName (unew->ukind),
07837                             uentry_getName (unew), 
07838                             uentry_isDeclared (old),
07839                             multiVal_unparse (newVal)),
07840                    uentry_whereDeclared (unew)))
07841                 {
07842                   uentry_showWhereLastExtra (old, multiVal_unparse (oldVal));
07843                 }
07844             }
07845           
07846           unew->info->uconst->val = multiVal_copy (oldVal);
07847           multiVal_free (newVal);
07848         }
07849       else
07850         {
07851           ;
07852         }
07853     }
07854   else
07855     {
07856       old->info->uconst->val = multiVal_copy (newVal);
07857     }
07858 }
07859 
07860 static void 
07861 uentry_checkConformance (/*@unique@*/ /*@notnull@*/ uentry old, 
07862                          /*@notnull@*/ uentry unew, bool mustConform,
07863                          bool completeConform)
07864 {
07865   bool typeError = FALSE;
07866   bool fcnConformance = FALSE;
07867 
07868   if (!ekind_equal (unew->ukind, old->ukind))
07869     {
07870       /*
07871       ** okay, only if one is a function and the other is
07872       ** a variable of type function.
07873       */
07874 
07875       if (unew->ukind == KENUMCONST
07876           && old->ukind == KCONST)
07877         {
07878           old->ukind = KENUMCONST;
07879           goto nokinderror;
07880         }
07881 
07882       if (unew->ukind == KFCN 
07883           && old->ukind == KCONST
07884           && ctype_isUnknown (old->utype))
07885         {
07886           /*
07887           ** When a function is defined with an unparam macro
07888           */
07889 
07890           uentry_copyInto (old, unew);
07891           return;
07892         }
07893 
07894       if (uentry_isExpandedMacro (old) 
07895           && uentry_isEitherConstant (unew))
07896         {
07897           uentry_copyInto (old, unew);
07898           return;
07899         }
07900 
07901       if (uentry_isEndIter (unew))
07902         {
07903           if (ctype_isUnknown (old->utype))
07904             {
07905               if (!uentry_isSpecified (old)
07906                   && uentry_isCodeDefined (unew))
07907                 {
07908                   if (!fileloc_withinLines (uentry_whereDefined (old),
07909                                             uentry_whereDeclared (unew), 2))
07910                     { /* bogus!  will give errors if there is too much whitespace */
07911                       voptgenerror
07912                         (FLG_SYNTAX,
07913                          message
07914                          ("Iterator finalized name %q does not match name in "
07915                           "previous iter declaration (should be end_%q).  This iter "
07916                           "is declared at %q", 
07917                           uentry_getName (unew),
07918                           uentry_getName (old),
07919                           fileloc_unparse (uentry_whereDefined (old))),
07920                          uentry_whereDeclared (old));
07921                     }
07922                 }
07923 
07924               uentry_copyInto (old, unew);
07925               return;
07926             }
07927           else
07928             {
07929               KindConformanceError (old, unew, mustConform);
07930             }
07931         }
07932 
07933       if (uentry_isFunction (unew))
07934         {
07935           if (uentry_isVariable (old))
07936             {
07937               if (!ctype_isUnknown (old->utype))
07938                 {
07939                   if (ctype_isFunction (old->utype))
07940                     {
07941                       uentry_makeVarFunction (old);
07942                       checkFunctionConformance (old, unew, mustConform,
07943                                                 completeConform);
07944                       fcnConformance = TRUE;
07945                     }
07946                   else
07947                     {
07948                       KindConformanceError (old, unew, mustConform);
07949                     }
07950                 }
07951               else
07952                 {
07953                   if (uentry_isExpandedMacro (old))
07954                     {
07955                       if (fileloc_isUndefined (unew->whereDefined))
07956                         {
07957                           unew->whereDefined = fileloc_update (unew->whereDefined, 
07958                                                               old->whereDefined);
07959                         }
07960 
07961                       uentry_copyInto (old, unew);
07962                       old->used = unew->used = TRUE;
07963                       return;
07964                     }
07965                   else
07966                     {
07967                       /* undeclared identifier */
07968                       old->utype = unew->utype;
07969                       uentry_makeVarFunction (old);
07970                       checkFunctionConformance (old, unew, FALSE, FALSE);
07971                       fcnConformance = TRUE;
07972                     }
07973                 }
07974             }
07975           else
07976             {
07977               KindConformanceError (old, unew, mustConform);
07978             }
07979         }
07980       else if (uentry_isFunction (old) && uentry_isVariable (unew))
07981         {
07982           if (!ctype_isUnknown (unew->utype))
07983             {
07984               if (ctype_isFunction (unew->utype))
07985                 {
07986                   uentry_makeVarFunction (unew);
07987                   checkFunctionConformance (old, unew, mustConform, completeConform);
07988                   fcnConformance = TRUE;
07989                 }
07990               else
07991                 {
07992                   KindConformanceError (old, unew, mustConform);
07993                 }
07994             }
07995           else
07996             {
07997               KindConformanceError (old, unew, mustConform);
07998             }
07999         }
08000       else
08001         {
08002           KindConformanceError (old, unew, mustConform);
08003         }
08004     }
08005   else
08006     {
08007       /*
08008       ** check parameter lists for functions 
08009       ** (before type errors, to get better messages
08010       */
08011 
08012       if (uentry_isFunction (old))
08013         {
08014           checkFunctionConformance (old, unew, mustConform, completeConform);
08015           fcnConformance = TRUE;
08016         }
08017       else 
08018         {
08019           if (!ctype_isUndefined (old->utype))
08020             {
08021               typeError = checkTypeConformance (old, unew, mustConform);
08022             }
08023         }
08024     }
08025 
08026  nokinderror:
08027 
08028   if (uentry_isEitherConstant (old) && uentry_isEitherConstant (unew))
08029     {
08030       uentry_checkConstantConformance (old, unew, mustConform, completeConform);
08031     }
08032 
08033   if (uentry_isDatatype (old) && uentry_isDatatype (unew))
08034     {
08035       uentry_checkDatatypeConformance (old, unew, mustConform, completeConform);
08036     }
08037 
08038   if (uentry_isVariable (old) && uentry_isVariable (unew))
08039     {
08040       if (!typeError && 
08041           !ctype_matchDef (old->utype, unew->utype))
08042         {
08043           if (optgenerror 
08044               (FLG_INCONDEFS,
08045                message
08046                ("Variable %q %s with inconsistent type (arrays and pointers are "
08047                 "not identical in variable declarations): %t",
08048                 uentry_getName (unew), 
08049                 uentry_reDefDecl (old, unew),
08050                 unew->utype),
08051                uentry_whereDeclared (unew)))
08052             {
08053               uentry_showWhereLast (old);
08054               
08055               /*
08056               ** Avoid repeated errors.
08057               */
08058 
08059               if (uentry_isCodeDefined (old) && uentry_isCodeDefined (unew))
08060                 {
08061                   old->whereDefined = fileloc_update (old->whereDefined,
08062                                                       fileloc_undefined);
08063                 }
08064 
08065               typeError = TRUE;
08066             }
08067         }
08068 
08069       checkVarConformance (old, unew, mustConform, completeConform);
08070     }
08071 
08072   if (fcnConformance)
08073     {
08074       /* old->utype = unew->utype; */
08075     }
08076   else
08077     {
08078       if (ctype_isConj (old->utype))
08079         {
08080           if (ctype_isConj (unew->utype))
08081             {
08082               if (!ctype_sameAltTypes (old->utype, unew->utype))
08083                 {
08084                   if (optgenerror 
08085                       (FLG_INCONDEFS,
08086                        message ("%s %q inconsistently %rdeclared with "
08087                                 "alternate types %s "
08088                                 "(types match, but alternates are not identical, "
08089                                 "so checking may not be correct)",
08090                                 ekind_capName (uentry_getKind (old)),
08091                                 uentry_getName (unew),
08092                                 uentry_isDeclared (old),
08093                                 ctype_unparse (unew->utype)),
08094                        uentry_whereDeclared (unew)))
08095                     {
08096                       uentry_showWhereLastVal (old, ctype_unparse (old->utype));
08097                     }
08098                   else
08099                     {
08100                       old->utype = unew->utype;
08101                     }
08102                 }
08103             }
08104         }
08105       else
08106         {
08107           if (ctype_isUnknown (old->utype))
08108             {
08109               old->utype = unew->utype;
08110             }
08111         }
08112     }  
08113 
08114   if (unew->ukind == old->ukind) 
08115     {
08116       sfree (unew->info);
08117       unew->info = uinfo_copy (old->info, old->ukind);
08118     }
08119 
08120   sRef_storeState (old->sref);
08121   sRef_storeState (unew->sref);
08122 }
08123 
08124 /*
08125 ** modifies spec to reflect def, reports any inconsistencies
08126 */
08127 
08128 void
08129 uentry_mergeEntries (uentry spec, /*@only@*/ uentry def)
08130 {
08131   llassert (uentry_isValid (spec));
08132   llassert (uentry_isValid (def));
08133   llassert (cstring_equal (spec->uname, def->uname));
08134 
08135   uentry_checkConformance (spec, def, TRUE, 
08136                            context_getFlag (FLG_NEEDSPEC));
08137 
08138   /* was: !(fileloc_isImport (uentry_whereSpecified (spec)))); */
08139 
08140   /*
08141   ** okay, declarations conform.  Propagate extra information.
08142   */
08143 
08144   uentry_setDefined (spec, uentry_whereDefined (def));
08145   uentry_setDeclared (spec, uentry_whereDeclared (def));
08146 
08147   if (uentry_isStatic (def))
08148     {
08149       if (optgenerror 
08150           (FLG_INCONDEFS,
08151            message ("%s %q specified, but declared as static",
08152                     ekind_capName (def->ukind),
08153                     uentry_getName (def)),
08154            uentry_whereDeclared (def)))
08155         {
08156           uentry_showWhereSpecified (spec);
08157         }
08158     }
08159   else 
08160     {
08161       spec->storageclass = def->storageclass;
08162     }
08163 
08164   sRef_storeState (spec->sref);
08165 
08166   spec->used = def->used || spec->used;
08167   spec->hasNameError |= def->hasNameError;
08168 
08169   uentry_free (def);
08170 
08171   if (!spec->hasNameError)
08172     {
08173       uentry_checkName (spec);
08174     }
08175   else
08176     {
08177       ;
08178     }
08179 }
08180 
08181 /*
08182 ** Can't generate function redeclaration errors when the 
08183 ** entries are merged, since we don't yet know if its the
08184 ** definition of the function.
08185 */
08186 
08187 void
08188 uentry_clearDecl (void)
08189 {
08190   posRedeclared = uentry_undefined;
08191   fileloc_free (posLoc);
08192   posLoc = fileloc_undefined;
08193 }
08194 
08195 void
08196 uentry_checkDecl (void)
08197 {
08198   if (uentry_isValid (posRedeclared))
08199     {
08200       llassert (fileloc_isDefined (posLoc));
08201 
08202       if (uentry_isCodeDefined (posRedeclared))
08203         {
08204           if (optgenerror (FLG_REDECL,
08205                            message ("%s %q declared after definition", 
08206                                     ekind_capName (posRedeclared->ukind),
08207                                     uentry_getName (posRedeclared)),
08208                            posLoc))
08209             {
08210               llgenindentmsg (message ("Definition of %q", 
08211                                        uentry_getName (posRedeclared)),
08212                               posRedeclared->whereDeclared);
08213             }
08214         }
08215       else
08216         {
08217           if (optgenerror (FLG_REDECL,
08218                            message ("%s %q declared more than once", 
08219                                     ekind_capName (posRedeclared->ukind),
08220                                     uentry_getName (posRedeclared)),
08221                            posLoc))
08222             {
08223               llgenindentmsg (message ("Previous declaration of %q", 
08224                                        uentry_getName (posRedeclared)),
08225                               posRedeclared->whereDeclared);
08226             }
08227         }
08228     }
08229 
08230   fileloc_free (posLoc);
08231   posLoc = fileloc_undefined;
08232   posRedeclared = uentry_undefined;
08233 }
08234 
08235 /*
08236 ** Redefinition of old as unew.
08237 ** modifies old to reflect unew, reports any inconsistencies
08238 */
08239 
08240 void
08241 uentry_mergeDefinition (uentry old, /*@only@*/ uentry unew)
08242 {
08243   fileloc olddef = uentry_whereDeclared (old);
08244   fileloc unewdef = uentry_whereDeclared (unew);
08245   bool mustConform;
08246   bool wasForward;
08247  
08248   if (uentry_isExtern (unew))
08249     {
08250       uentry_setUsed (old, unewdef);
08251     }
08252 
08253   wasForward = 
08254     fileloc_isUndefined (olddef) 
08255       && fileloc_isDefined (uentry_whereDefined (old)) 
08256         && !uentry_isExpandedMacro (old);
08257   
08258   if (!context_getFlag (FLG_INCONDEFSLIB)
08259       && (fileloc_isLib (olddef) || fileloc_isImport (olddef)))
08260     {
08261       mustConform = FALSE;
08262     }
08263   else
08264     {
08265       mustConform = TRUE;
08266     }
08267   
08268   llassert (uentry_isValid (old));
08269   llassert (uentry_isValid (unew));
08270   llassert (cstring_equal (old->uname, unew->uname));
08271 
08272   /*
08273   ** should check old one was extern!
08274   */
08275 
08276   if (uentry_isStatic (old))
08277     {
08278       if (!(uentry_isStatic (unew)))
08279         {
08280           if (optgenerror 
08281               (FLG_SHADOW,
08282                message ("%s %q shadows static declaration",
08283                         ekind_capName (unew->ukind),
08284                         uentry_getName (unew)),
08285                unewdef))
08286             {
08287               uentry_showWhereLast (old);
08288             }
08289         }
08290       else
08291         {
08292           uentry_setDeclDef (old, unewdef);
08293         }
08294     }
08295   else if (uentry_isStatic (unew))
08296     {
08297       uentry_setDeclDef (old, unewdef);
08298     }
08299   else if (uentry_isExtern (old))
08300     {
08301       uentry_setDeclared (old, unewdef);
08302     }
08303   else
08304     {
08305       if (!uentry_isExtern (unew) && !uentry_isForward (old)
08306           && !fileloc_equal (olddef, unewdef)
08307           && !fileloc_isUndefined (olddef)
08308           && !fileloc_isUndefined (unewdef)
08309           && !fileloc_isBuiltin (olddef)
08310           && !fileloc_isBuiltin (unewdef)
08311           && !uentry_isYield (old)
08312           && !(fileloc_isLib (olddef) || fileloc_isImport (olddef)))
08313         {
08314           if (uentry_isVariable (old) || uentry_isVariable (unew))
08315             {
08316               ; /* will report redeclaration error later */
08317             }
08318           else
08319             {
08320               if (fileloc_isDefined (uentry_whereDefined (old)))
08321                 {
08322                   if (optgenerror
08323                       (FLG_REDEF,
08324                        message ("%s %q defined more than once", 
08325                                 ekind_capName (unew->ukind),
08326                                 uentry_getName (unew)),
08327                        uentry_whereLast (unew)))
08328                     {
08329                       llgenindentmsg
08330                         (message ("Previous definition of %q", 
08331                                   uentry_getName (old)),
08332                          uentry_whereLast (old));
08333                     }
08334                   /*
08335                   if (uentry_isDatatype (old) || uentry_isAnyTag (old))
08336                     {
08337                       uentry_copyInto (old, unew);
08338                       old->sref = sRef_saveCopy (old->sref);
08339                     }
08340                     */
08341                 }
08342             }
08343         }
08344       else
08345         {
08346           if (fileloc_isLib (olddef)
08347               || fileloc_isUndefined (olddef)
08348               || fileloc_isImport (olddef))
08349             {
08350               if (uentry_isExtern (unew)) 
08351                 {
08352                   if (uentry_isExtern (old)
08353                       || (fileloc_isDefined (uentry_whereDeclared (old))
08354                           && (!fileloc_equal (uentry_whereDeclared (old),
08355                                               uentry_whereDefined (old)))))
08356                     {
08357                       if (optgenerror
08358                           (FLG_REDECL,
08359                            message ("%s %q declared more than once", 
08360                                     ekind_capName (unew->ukind),
08361                                     uentry_getName (unew)),
08362                            unew->whereDeclared))
08363                         {
08364                           llgenindentmsg
08365                             (message ("Previous declaration of %q", 
08366                                       uentry_getName (old)),
08367                              old->whereDeclared);
08368                         }
08369                     }
08370                   
08371                   uentry_setExtern (old);
08372                 }
08373               else
08374                 {
08375                   uentry_setDefined (old, unewdef);
08376                 }
08377             }
08378         }
08379     }
08380 
08381   uentry_checkConformance (old, unew, mustConform, FALSE);
08382 
08383   old->used = old->used || unew->used;
08384   old->uses = filelocList_append (old->uses, unew->uses);
08385   unew->uses = filelocList_undefined; 
08386 
08387   sRef_storeState (old->sref); 
08388   sRef_storeState (unew->sref);
08389 
08390   if (wasForward)
08391     {
08392       old->whereDefined = fileloc_update (old->whereDefined,
08393                                           fileloc_undefined);
08394     }
08395 
08396   /*
08397   ** No redeclaration errors for functions here, since we
08398   ** don't know if this is the definition of the function.
08399   */
08400 
08401   if (fileloc_isUser (old->whereDeclared)
08402       && fileloc_isUser (unew->whereDeclared)
08403       && !fileloc_equal (old->whereDeclared, unew->whereDeclared)
08404       && !fileloc_isDefined (unew->whereDefined))
08405     {
08406       if (uentry_isFunction (old))
08407         {
08408           /*@-temptrans@*/ posRedeclared = old; /*@=temptrans@*/
08409           posLoc = fileloc_update (posLoc, unew->whereDeclared);
08410         }
08411       else
08412         {
08413           if (optgenerror (FLG_REDECL,
08414                            message ("%s %q declared more than once", 
08415                                     ekind_capName (unew->ukind),
08416                                     uentry_getName (unew)),
08417                            unew->whereDeclared))
08418             {
08419               llgenindentmsg (message ("Previous declaration of %q", 
08420                                        uentry_getName (old)),
08421                               old->whereDeclared);
08422             }
08423         }
08424     }
08425 
08426   if (fileloc_isUndefined (old->whereDefined))
08427     {
08428       old->whereDefined = fileloc_update (old->whereDefined, unew->whereDefined);
08429     }
08430   else
08431     {
08432       if (!context_processingMacros ()
08433           && fileloc_isUser (old->whereDefined) 
08434           && fileloc_isUser (unew->whereDefined)
08435           && !fileloc_equal (old->whereDefined, unew->whereDefined))
08436         {
08437           if (uentry_isVariable (unew) || uentry_isFunction (unew))
08438             {
08439               if (uentry_isVariable (unew) 
08440                   && uentry_isExtern (unew))
08441                 {
08442                   if (optgenerror (FLG_REDECL,
08443                                    message ("%s %q declared after definition", 
08444                                             ekind_capName (unew->ukind),
08445                                             uentry_getName (unew)),
08446                                    unew->whereDeclared))
08447                     {
08448                       llgenindentmsg (message ("Definition of %q", 
08449                                                uentry_getName (old)),
08450                                       old->whereDefined);
08451                     }
08452                 }
08453               else
08454                 {
08455                   if (optgenerror (FLG_REDEF,
08456                                    message ("%s %q redefined", 
08457                                             ekind_capName (unew->ukind),
08458                                             uentry_getName (unew)),
08459                                    unew->whereDefined))
08460                     {
08461                       llgenindentmsg (message ("Previous definition of %q", 
08462                                                uentry_getName (old)),
08463                                       old->whereDefined);
08464                     }
08465                 }
08466             }
08467         }
08468     }
08469 
08470   if (uentry_isExternal (unew))
08471     {
08472       old->whereDefined = fileloc_createExternal ();
08473     }
08474 
08475   if (unew->hasNameError)
08476     {
08477       old->hasNameError = TRUE;
08478     }
08479 
08480   uentry_free (unew);
08481 
08482   if (!old->hasNameError)
08483     {
08484       uentry_checkName (old);
08485     }
08486 
08487   llassert (!ctype_isUndefined (old->utype));
08488 }
08489 
08490 void
08491 uentry_copyState (uentry res, uentry other)
08492 {
08493   llassert (uentry_isValid (res));
08494   llassert (uentry_isValid (other));
08495 
08496   res->used = other->used;
08497 
08498   res->info->var->kind = other->info->var->kind;
08499   res->info->var->defstate = other->info->var->defstate;
08500   res->info->var->nullstate = other->info->var->nullstate;
08501   res->info->var->checked = other->info->var->checked;
08502 
08503   sRef_copyState (res->sref, other->sref);
08504 }
08505 
08506 bool
08507 uentry_sameKind (uentry u1, uentry u2)
08508 {
08509   if (uentry_isValid (u1) && uentry_isValid (u2))
08510     {
08511       if (uentry_isVar (u1) && uentry_isVar (u2))
08512         {
08513           ctype c1 = u1->utype;
08514           ctype c2 = u2->utype;
08515 
08516           if (ctype_isUnknown (c1) || ctype_isUnknown (c2)) return FALSE;
08517 
08518           /*
08519           ** both functions, or both not functions
08520           */
08521 
08522           return (bool_equal (ctype_isFunction (c1), ctype_isFunction (c2)));
08523         }
08524       else
08525         {
08526           return ((u1->ukind == u2->ukind));
08527         }
08528     }
08529   
08530   return FALSE;
08531 }
08532    
08533 static void uentry_copyInto (/*@unique@*/ uentry unew, uentry old)
08534 {
08535   llassert (uentry_isValid (unew));
08536   llassert (uentry_isValid (old));
08537 
08538   unew->ukind = old->ukind;
08539   unew->uname = cstring_copy (old->uname);
08540   unew->utype = old->utype;
08541 
08542   unew->whereSpecified = fileloc_copy (old->whereSpecified);
08543   unew->whereDefined = fileloc_copy (old->whereDefined);
08544   unew->whereDeclared = fileloc_copy (old->whereDeclared);
08545 
08546   unew->sref = sRef_saveCopy (old->sref); /* Memory leak! */
08547   unew->used = old->used;
08548   unew->lset = FALSE;
08549   unew->isPrivate = old->isPrivate;
08550   unew->hasNameError = old->hasNameError;
08551   unew->uses = filelocList_undefined;
08552 
08553   unew->storageclass = old->storageclass;
08554   unew->info = uinfo_copy (old->info, old->ukind);
08555 }
08556 
08557 
08558 uentry
08559 uentry_copy (uentry e)
08560 {
08561   if (uentry_isValid (e))
08562     {
08563       uentry enew = uentry_alloc ();
08564       DPRINTF (("copy: %s", uentry_unparseFull (e)));
08565       uentry_copyInto (enew, e);
08566       DPRINTF (("Here we are..."));
08567       DPRINTF (("original: %s", uentry_unparseFull (e)));
08568       DPRINTF (("copy: %s", uentry_unparse (enew)));
08569       DPRINTF (("copy: %s", uentry_unparseFull (enew)));
08570       return enew;
08571     }
08572   else
08573     {
08574       return uentry_undefined;
08575     }
08576 }
08577 
08578 void
08579 uentry_setState (uentry res, uentry other)
08580 {
08581   llassert (uentry_isValid (res));
08582   llassert (uentry_isValid (other));
08583 
08584   llassert (res->ukind == other->ukind);
08585   llassert (res->ukind == KVAR);
08586 
08587   res->sref = sRef_saveCopy (other->sref);
08588   res->used = other->used;
08589   filelocList_free (res->uses); 
08590   res->uses = other->uses; 
08591   other->uses = filelocList_undefined; 
08592   res->lset = other->lset;
08593 }
08594 
08595 void
08596 uentry_mergeUses (uentry res, uentry other)
08597 {
08598   llassert (uentry_isValid (res));
08599   llassert (uentry_isValid (other));
08600 
08601   res->used = other->used || res->used;
08602   res->lset = other->lset || res->lset;
08603   res->uses = filelocList_append (res->uses, other->uses);
08604   other->uses = filelocList_undefined;
08605 }
08606 
08607 
08608 /*
08609 ** This is a really ugly routine.
08610 **
08611 ** gack...fix this one day.
08612 */
08613 
08614 /*
08615 ** flip == TRUE
08616 **   >> res is the false branch, other is the true branch (or continuation)
08617 ** flip == FALSE
08618 **   >> res is the true branch, other is the false branch (or continutation)
08619 **
08620 ** opt == TRUE if,
08621 **
08622 ** <other>
08623 ** if <res> ;
08624 **
08625 ** References not effected by res are propagated from other.
08626 */
08627 
08628 static void
08629   branchStateError (/*@notnull@*/ uentry res, /*@notnull@*/ uentry other, 
08630                     bool flip, clause cl, fileloc loc)
08631 {
08632   if (optgenerror 
08633       (FLG_BRANCHSTATE,
08634        message ("%s %q is %s %s, but %s %s.",
08635                 ekind_capName (res->ukind), uentry_getName (res),
08636                 sRef_stateVerb (res->sref), clause_nameFlip (cl, flip),
08637                 sRef_stateAltVerb (res->sref), clause_nameFlip (cl, !flip)),
08638        loc))
08639     {
08640       if (sRef_isDead (res->sref))
08641         {
08642           sRef_showStateInfo (res->sref);
08643         }
08644       else if (sRef_isKept (res->sref))
08645         {
08646           sRef_showAliasInfo (res->sref);
08647         }
08648       else /* dependent */
08649         {
08650           sRef_showAliasInfo (res->sref);
08651           sRef_showAliasInfo (other->sref);
08652         }
08653       
08654       sRef_setAliasKind (res->sref, AK_ERROR, fileloc_undefined);
08655     }
08656 }
08657 
08658 static bool incompatibleStates (sRef rs, sRef os)
08659 {
08660   alkind rk = sRef_getAliasKind (rs);
08661   alkind ok = sRef_getAliasKind (os);
08662 
08663   if (alkind_isError (rk) || alkind_isError (ok))
08664     {
08665       return FALSE;
08666     }
08667   else
08668     {
08669       return ((sRef_isDead (rs)
08670                || (alkind_isKept (rk) && !alkind_isKept (ok))
08671                || (alkind_isDependent (rk) 
08672                    && !alkind_isDependent (ok) && !alkind_isTemp (ok)))
08673               && (sRef_isAllocated (os) || sRef_isStateDefined (os)));
08674     }
08675 }
08676 
08677 static void
08678   branchStateAltError (/*@notnull@*/ uentry res,
08679                        /*@notnull@*/ uentry other, bool flip,
08680                        clause cl, fileloc loc)
08681 {
08682   if (optgenerror 
08683       (FLG_BRANCHSTATE,
08684        message ("%s %q is %s %s, but %s %s.",
08685                 ekind_capName (res->ukind), uentry_getName (res),
08686                 sRef_stateVerb (other->sref), clause_nameFlip (cl, flip),
08687                 sRef_stateAltVerb (other->sref), clause_nameFlip (cl, !flip)),
08688        loc))
08689     {
08690       if (sRef_isDead (other->sref))
08691         {
08692           sRef_showStateInfo (other->sref);
08693         }
08694       else /* kept */
08695         {
08696           sRef_showAliasInfo (other->sref);
08697         }
08698       
08699       sRef_setAliasKind (res->sref, AK_ERROR, fileloc_undefined);
08700       sRef_setDefinedComplete (res->sref, fileloc_undefined);
08701       
08702       sRef_setAliasKind (other->sref, AK_ERROR, fileloc_undefined);
08703       sRef_setDefinedComplete (other->sref, fileloc_undefined);
08704     }
08705 }
08706 
08707 static bool notNull (sRef sr, bool flip)
08708 {
08709   return (!sRef_definitelyNull (sr)
08710           && !(sRef_isKept (sr))
08711           && !(sRef_isDependent (sr))
08712           && !(flip ? usymtab_isProbableDeepNull (sr)
08713                : usymtab_isAltProbablyDeepNull (sr)));
08714 }
08715     
08716 void
08717 uentry_mergeState (uentry res, uentry other, fileloc loc,
08718                    bool mustReturn, bool flip, bool opt,
08719                    clause cl)
08720 {
08721   llassert (uentry_isValid (res));
08722   llassert (uentry_isValid (other));
08723 
08724   llassert (res->ukind == other->ukind);
08725   llassert (res->ukind == KVAR);
08726 
08727   DPRINTF (("Merge state: %s / %s", 
08728             uentry_unparse (res),
08729             uentry_unparse (other)));
08730 
08731   if (sRef_isValid (res->sref))
08732     {
08733       if (!mustReturn)
08734         {
08735           if (incompatibleStates (res->sref, other->sref))
08736             {
08737               if (sRef_isThroughArrayFetch (res->sref)
08738                   && !context_getFlag (FLG_STRICTBRANCHSTATE))
08739                 {
08740                   if (sRef_isKept (res->sref) || sRef_isKept (other->sref))
08741                     {
08742                       sRef_maybeKill (res->sref, loc);
08743                     }
08744                   else if (sRef_isPossiblyDead (other->sref))
08745                     {
08746                       sRef_maybeKill (res->sref, loc);
08747                     }
08748                   else
08749                     {
08750                       ;
08751                     }
08752                 }
08753               else
08754                 {
08755                   if (notNull (other->sref, flip))
08756                     {
08757                       if (sRef_isLocalParamVar (res->sref) 
08758                           && (sRef_isLocalState (other->sref) 
08759                               || sRef_isDependent (other->sref)))
08760                         {
08761                           if (sRef_isDependent (res->sref))
08762                             {
08763                               sRef_setDependent (other->sref, loc);
08764                             }
08765                           else
08766                             {
08767                               sRef_setDefState (res->sref, SS_UNUSEABLE, loc);
08768                             }
08769                         }
08770                       else 
08771                         {
08772                           branchStateError (res, other, flip, cl, loc);
08773                         }
08774                     }
08775                 }
08776               
08777               if (sRef_isKept (res->sref))
08778                 {
08779                   sRef_setKept (other->sref, loc);
08780                 }
08781             }
08782           else
08783             {
08784               if (incompatibleStates (other->sref, res->sref))
08785                 {
08786                   if (notNull (res->sref, !flip))
08787                     {
08788                       if (sRef_isLocalParamVar (res->sref) 
08789                           && (sRef_isDependent (res->sref)
08790                               || sRef_isLocalState (res->sref)))
08791                         {
08792                           if (sRef_isDependent (other->sref))
08793                             {
08794                               sRef_setDependent (res->sref, loc);
08795                             }
08796                           else
08797                             {
08798                               sRef_setDefState (res->sref, SS_UNUSEABLE, loc);
08799                             }
08800                         }
08801                       else
08802                         {
08803                           if (sRef_isParam (other->sref))
08804                             {
08805                               /* 
08806                               ** If the local variable associated
08807                               ** with the param has the correct state,
08808                               ** its okay.
08809                               ** (e.g., free (s); s = new(); ...
08810                               */
08811 
08812                               uentry uvar = usymtab_lookupSafe (other->uname);
08813 
08814                               if (uentry_isValid (uvar)
08815                                   && ((sRef_isDead (other->sref) 
08816                                        && sRef_isOnly (uvar->sref))
08817                                       || (sRef_isDependent (other->sref)
08818                                           && sRef_isOwned (uvar->sref))))
08819                                 {
08820                                   /* no error */
08821                                 }
08822                               else
08823                                 {
08824                                   branchStateAltError (res, other,
08825                                                        flip, cl, loc);
08826                                 }
08827                             }
08828                           else
08829                             {
08830                               branchStateAltError (res, other, 
08831                                                    flip, cl, loc);
08832                             }
08833                         }
08834                     }
08835                 }
08836 
08837               if (sRef_isKept (other->sref))
08838                 {
08839                   sRef_setKept (res->sref, loc);
08840                 }
08841             }
08842           
08843           if (opt)
08844             {
08845               DPRINTF (("Merge opt..."));
08846               sRef_mergeOptState (res->sref, other->sref, cl, loc);
08847               DPRINTF (("Done!"));
08848             }
08849           else
08850             {
08851               sRef_mergeState (res->sref, other->sref, cl, loc);
08852             }
08853         }
08854       else
08855         {
08856           if (sRef_isModified (other->sref))
08857             {
08858               sRef_setModified (res->sref);
08859             }
08860         }
08861 
08862       if (cl == DOWHILECLAUSE)
08863         {
08864           res->used = other->used || res->used;
08865           res->lset = other->lset || res->lset;
08866           res->uses = filelocList_append (res->uses, other->uses);
08867           other->uses = filelocList_undefined;
08868         }
08869       else
08870         {
08871           if (sRef_isMacroParamRef (res->sref)
08872               && !uentry_isSefParam (other)
08873               && !uentry_isSefParam (res))
08874             {
08875               bool hasError = FALSE;
08876               
08877               if (bool_equal (res->used, other->used))
08878                 {
08879                   res->used = other->used;
08880                 }
08881               else
08882                 {
08883                   if (other->used && !flip)
08884                     {
08885                       hasError = 
08886                         optgenerror 
08887                           (FLG_MACROPARAMS,
08888                            message ("Macro parameter %q used in true clause, "
08889                                     "but not in false clause",
08890                                     uentry_getName (res)),
08891                            uentry_whereDeclared (res));
08892                     }
08893                   else
08894                     {   
08895                       hasError = 
08896                         optgenerror 
08897                           (FLG_MACROPARAMS,
08898                            message ("Macro parameter %q used in false clause, "
08899                                     "but not in true clause",
08900                                     uentry_getName (res)),
08901                            uentry_whereDeclared (res));
08902                     }
08903                   res->used = TRUE;
08904                   
08905                   if (hasError)
08906                     {
08907                       /* make it sef now, prevent more errors */
08908                       res->info->var->kind = VKREFSEFPARAM;
08909                     }
08910                 }
08911             }
08912           else
08913             {
08914               res->used = other->used || res->used;
08915               res->lset = other->lset || res->lset;
08916               res->uses = filelocList_append (res->uses, other->uses);
08917               other->uses = filelocList_undefined;
08918             }
08919         }
08920     }
08921 }
08922 
08923 void uentry_setUsed (uentry e, fileloc loc)
08924 {
08925   static bool firstTime = TRUE;
08926   static bool showUses = FALSE;
08927   static bool exportLocal = FALSE;
08928 
08929   if (firstTime)
08930     {
08931       /* need to track uses is FLG_SHOWUSES or FLG_EXPORTLOCAL is true */
08932 
08933       showUses = context_getFlag (FLG_SHOWUSES); 
08934       exportLocal = context_maybeSet (FLG_EXPORTLOCAL);
08935 
08936       firstTime = FALSE;
08937     }
08938 
08939   if (uentry_isValid (e))
08940     {
08941       int dp;
08942       
08943       if (sRef_isMacroParamRef (e->sref))
08944         {
08945           if (uentry_isYield (e) || uentry_isSefParam (e))
08946             {
08947               ;
08948             }
08949           else 
08950             {
08951               if (context_inConditional ())
08952                 {
08953                   if (optgenerror
08954                       (FLG_MACROPARAMS,
08955                        message ("Macro parameter %q used in conditionally "
08956                                 "executed code (may or may not be "
08957                                 "evaluated exactly once)", 
08958                                 uentry_getName (e)),
08959                        loc))
08960                     {
08961                       e->info->var->kind = VKREFSEFPARAM;
08962                     }
08963                 }
08964               else
08965                 {
08966                   if ((e)->used)
08967                     {
08968                       if (optgenerror
08969                           (FLG_MACROPARAMS,
08970                            message ("Macro parameter %q used more than once", 
08971                                     uentry_getName (e)),
08972                            uentry_whereDeclared (e)))
08973                         {
08974                           e->info->var->kind = VKREFSEFPARAM;
08975                         }
08976                     }
08977                 }
08978             }
08979         }
08980       
08981       if ((dp = uentry_directParamNo (e)) >= 0)
08982         {
08983           uentry_setUsed (usymtab_getParam (dp), loc);
08984         }
08985       
08986       e->used = TRUE;
08987       
08988       if (!sRef_isLocalVar (e->sref))
08989         {
08990           if (showUses)
08991             {
08992               e->uses = filelocList_add (e->uses, fileloc_copy (loc));
08993             }
08994           else 
08995             {
08996               if (exportLocal)
08997                 {
08998                   if (context_inMacro ())
08999                     {
09000                       e->uses = filelocList_addUndefined (e->uses);
09001                     }
09002                   else 
09003                     {
09004                       e->uses = filelocList_addDifferentFile
09005                         (e->uses, 
09006                          uentry_whereDeclared (e),
09007                          loc);
09008                     }
09009                 }
09010             }
09011         }
09012     }
09013 }
09014 
09015 bool uentry_isReturned (uentry u)
09016 {
09017   return (uentry_isValid (u) && uentry_isVar (u) 
09018           && (u->info->var->kind == VKRETPARAM
09019               || u->info->var->kind == VKSEFRETPARAM));
09020 }
09021 
09022 /*@exposed@*/ sRef uentry_returnedRef (uentry u, exprNodeList args)
09023 {
09024   llassert (uentry_isRealFunction (u));
09025 
09026   if (ctype_isFunction (u->utype)
09027       && sRef_isStateSpecial (uentry_getSref (u)))
09028     {
09029       specialClauses clauses = uentry_getSpecialClauses (u);
09030       sRef res = sRef_makeNew (ctype_returnValue (u->utype), u->sref, u->uname);
09031 
09032       sRef_setAllocated (res, g_currentloc);
09033 
09034       specialClauses_postElements (clauses, cl)
09035         {
09036           sRefSet refs = specialClause_getRefs (cl);
09037           sRefMod modf = specialClause_getEffectFunction (cl);
09038 
09039           sRefSet_elements (refs, el)
09040             {
09041               sRef base = sRef_getRootBase (el);
09042 
09043               if (sRef_isResult (base))
09044                 {
09045                   if (modf != NULL)
09046                     {
09047                       sRef sr = sRef_fixBase (el, res);
09048                       modf (sr, g_currentloc);
09049                     }
09050                 }
09051               else
09052                 {
09053                   ;
09054                 }
09055             } end_sRefSet_elements ;
09056 
09057         } end_specialClauses_postElements ;
09058 
09059       return res;
09060     }
09061   else
09062     {
09063       uentryList params;
09064       alkind ak;
09065       sRefSet prefs = sRefSet_new ();
09066       sRef res = sRef_undefined;
09067       int paramno = 0;
09068       
09069       params = uentry_getParams (u);
09070       
09071       uentryList_elements (params, current)
09072         {
09073           if (uentry_isReturned (current))
09074             {
09075               if (exprNodeList_size (args) >= paramno)
09076                 {
09077                   exprNode ecur = exprNodeList_nth (args, paramno);
09078                   sRef tref = exprNode_getSref (ecur);
09079                   
09080                   if (sRef_isValid (tref))
09081                     {
09082                       sRef tcref = sRef_copy (tref);
09083                       
09084                       if (sRef_isDead (tcref))
09085                         {
09086                           sRef_setDefined (tcref, g_currentloc);
09087                           sRef_setOnly (tcref, g_currentloc);
09088                         }
09089                       
09090                       if (sRef_isRefCounted (tcref))
09091                         {
09092                           /* could be a new ref now (but only if its returned) */
09093                           sRef_setAliasKindComplete (tcref, AK_ERROR, g_currentloc);
09094                         }
09095                       
09096                       sRef_makeSafe (tcref);
09097                       
09098                       prefs = sRefSet_insert (prefs, tcref);
09099                     }
09100                 }
09101             }
09102           
09103           paramno++;
09104         } end_uentryList_elements ;
09105       
09106       if (sRefSet_size (prefs) > 0)
09107         {
09108           nstate n = sRef_getNullState (u->sref);
09109           
09110           if (sRefSet_size (prefs) == 1)
09111             {
09112               res = sRefSet_choose (prefs);
09113             }
09114           else
09115             {
09116               res = sRefSet_mergeIntoOne (prefs);
09117             }
09118           
09119           if (nstate_isKnown (n))
09120             {
09121               sRef_setNullState (res, n, g_currentloc);
09122             }
09123         }
09124       else
09125         {
09126           if (ctype_isFunction (u->utype))
09127             {
09128               res = sRef_makeNew (ctype_returnValue (u->utype), u->sref, u->uname);
09129             }
09130           else
09131             {
09132               res = sRef_makeNew (ctype_unknown, u->sref, u->uname);
09133             }
09134           
09135           if (sRef_isRefCounted (res))
09136             {
09137               sRef_setAliasKind (res, AK_NEWREF, g_currentloc);
09138             }
09139         }
09140       
09141       if (sRef_getNullState (res) == NS_ABSNULL)
09142         {
09143           ctype ct = ctype_realType (u->utype);
09144           
09145           if (ctype_isAbstract (ct))
09146             {
09147               sRef_setNotNull (res, g_currentloc);
09148             }
09149           else
09150             {
09151               if (ctype_isUser (ct))
09152                 {
09153                   sRef_setStateFromUentry (res, usymtab_getTypeEntry (ctype_typeId (ct)));
09154                 }
09155               else
09156                 {
09157                   sRef_setNotNull (res, g_currentloc);
09158                 }
09159             }
09160         }
09161       
09162       if (sRef_isRefCounted (res))
09163         {
09164           sRef_setAliasKind (res, AK_NEWREF, g_currentloc);
09165         }
09166       else if (sRef_isKillRef (res))
09167         {
09168           sRef_setAliasKind (res, AK_REFCOUNTED, g_currentloc);
09169         }
09170       else
09171         {
09172           ;
09173         }
09174       
09175       ak = sRef_getAliasKind (res);
09176       
09177       if (alkind_isImplicit (ak))
09178         {
09179           sRef_setAliasKind (res, 
09180                              alkind_fixImplicit (ak),
09181                              g_currentloc);
09182         }
09183       
09184       sRefSet_free (prefs);
09185       
09186       return res;
09187     }
09188 }
09189 
09190 static bool uentry_isRefCounted (uentry ue)
09191 {
09192   ctype ct = uentry_getType (ue);
09193 
09194   if (ctype_isFunction (ct))
09195     {
09196       return (ctype_isRefCounted (ctype_returnValue (ct)));
09197     }
09198   else
09199     {
09200       return (ctype_isRefCounted (ct));
09201     }
09202 }
09203 
09204 /*
09205 ** old was declared yield in the specification.  
09206 ** new is declared in the iter implementation.
09207 */
09208 
09209 void uentry_checkYieldParam (uentry old, uentry unew)
09210 {
09211   cstring name;
09212 
09213   llassert (uentry_isVariable (old));
09214   llassert (uentry_isVariable (unew));
09215 
09216   unew->info->var->kind = VKYIELDPARAM;
09217   (void) checkTypeConformance (old, unew, TRUE);
09218   checkVarConformance (old, unew, TRUE, FALSE);
09219 
09220   /* get rid of param marker */
09221 
09222   name = uentry_getName (unew);
09223   cstring_free (unew->uname);
09224   unew->uname = name;
09225   unew->info->var->kind = VKREFYIELDPARAM;
09226 
09227   uentry_setUsed (old, fileloc_undefined);
09228   uentry_setUsed (unew, fileloc_undefined);
09229 }
09230 
09231 /*@observer@*/ cstring
09232 uentry_ekindName (uentry ue)
09233 {
09234   if (uentry_isValid (ue))
09235     {
09236       switch (ue->ukind)
09237         {
09238         case KINVALID:
09239           return cstring_makeLiteralTemp ("<Error: invalid uentry>");
09240         case KDATATYPE: 
09241           return cstring_makeLiteralTemp ("Datatype");
09242         case KENUMCONST:
09243           return cstring_makeLiteralTemp ("Enum member");
09244         case KCONST:  
09245           return cstring_makeLiteralTemp ("Constant");
09246         case KVAR:      
09247           if (uentry_isParam (ue))
09248             {
09249               return cstring_makeLiteralTemp ("Parameter");
09250             }
09251           else if (uentry_isExpandedMacro (ue))
09252             {
09253               return cstring_makeLiteralTemp ("Expanded macro");
09254             }
09255           else
09256             {
09257               return cstring_makeLiteralTemp ("Variable");
09258             }
09259         case KFCN:   
09260           return cstring_makeLiteralTemp ("Function");
09261         case KITER: 
09262           return cstring_makeLiteralTemp ("Iterator");
09263         case KENDITER:
09264           return cstring_makeLiteralTemp ("Iterator finalizer");
09265         case KSTRUCTTAG:
09266           return cstring_makeLiteralTemp ("Struct tag");
09267         case KUNIONTAG:
09268           return cstring_makeLiteralTemp ("Union tag");
09269         case KENUMTAG: 
09270           return cstring_makeLiteralTemp ("Enum tag");
09271         case KELIPSMARKER: 
09272           return cstring_makeLiteralTemp ("Optional parameters");
09273         }
09274     }
09275   else
09276     {
09277       return cstring_makeLiteralTemp ("<Undefined>");
09278     }
09279 
09280   BADEXIT;
09281 }
09282 
09283 void uentry_setHasNameError (uentry ue)
09284 {
09285   llassert (uentry_isValid (ue));
09286 
09287   ue->hasNameError = TRUE;
09288 }
09289 
09290 void uentry_checkName (uentry ue)
09291 {
09292   if (uentry_isValid (ue) 
09293       && !uentry_isElipsisMarker (ue)
09294       && context_getFlag (FLG_NAMECHECKS)
09295       && !ue->hasNameError 
09296       && !uentry_isEndIter (ue)
09297       && !fileloc_isBuiltin (uentry_whereLast (ue))
09298       && (uentry_isExpandedMacro (ue) || !uentry_isForward (ue)))
09299     {
09300       
09301       if (uentry_isPriv (ue))
09302         {
09303           ; /* any checks here? */
09304         }
09305       else if (fileloc_isExternal (uentry_whereDefined (ue)))
09306         {
09307           ; /* no errors for externals */
09308         }
09309       else
09310         {
09311           int scope;
09312           
09313           if (uentry_isExpandedMacro (ue))
09314             {
09315               scope = globScope;
09316             }
09317           else
09318             {
09319               if (uentry_isExpandedMacro (ue))
09320                 {
09321                   scope = fileScope;
09322                 }
09323               else if (uentry_isVariable (ue))
09324                 {
09325                   sRef sr = uentry_getSref (ue);
09326 
09327                   if (sRef_isValid (sr))
09328                     {
09329                       scope = sRef_getScope (sr);
09330                     }
09331                   else
09332                     {
09333                       scope = fileScope; 
09334                     }
09335                 }
09336               else if (uentry_isFunction (ue)
09337                        || uentry_isIter (ue)
09338                        || uentry_isEndIter (ue)
09339                        || uentry_isConstant (ue))
09340                 {
09341                   scope = uentry_isStatic (ue) ? fileScope : globScope;
09342                 }
09343               else /* datatypes, etc. must be global */
09344                 {
09345                   scope = globScope;
09346                 }
09347               
09348               usymtab_checkDistinctName (ue, scope);
09349             }
09350 
09351           if (context_getFlag (FLG_CPPNAMES)) 
09352             {
09353               if (checkCppName (uentry_rawName (ue), uentry_whereLast (ue)))
09354                 {
09355                   uentry_setHasNameError (ue);
09356                 }
09357             }
09358 
09359           if (scope == globScope)
09360             {
09361               checkGlobalName (ue);
09362 
09363               if (context_getFlag (FLG_ANSIRESERVED))
09364                 {
09365                   if (uentry_hasName (ue)
09366                       && !uentry_isAnyTag (ue))
09367                     {
09368                       if (checkAnsiName (uentry_rawName (ue),
09369                                          uentry_whereLast (ue)))
09370                         {
09371                           uentry_setHasNameError (ue);
09372                         }
09373                     }
09374                 }
09375             }
09376           else
09377             {
09378               checkLocalName (ue);
09379               
09380               if (context_getFlag (FLG_ANSIRESERVEDLOCAL))
09381                 {
09382                   if (uentry_hasName (ue)
09383                       && !uentry_isAnyTag (ue))
09384                     {
09385                       if (checkAnsiName (uentry_rawName (ue),
09386                                          uentry_whereLast (ue)))
09387                         {
09388                           uentry_setHasNameError (ue);
09389                         }
09390                     }
09391                 }
09392             }
09393 
09394           DPRINTF (("Check prefix: %s", uentry_unparse (ue)));
09395           checkPrefix (ue);
09396         }
09397     }
09398 }
09399 
09400 /*@exposed@*/ uentry uentry_makeUnrecognized (cstring c, /*@keep@*/ fileloc loc)
09401 {
09402   uentry ue;
09403   fileloc tloc;
09404 
09405   /*
09406   ** Can't but unrecognized ids in macros in global scope, because srefs will break! */
09407   if (!context_inMacro ())
09408     {
09409       sRef_setGlobalScopeSafe ();
09410     }
09411 
09412   ue = uentry_makeVariable (c, ctype_unknown, loc, FALSE);
09413   uentry_setUsed (ue, loc);               
09414   
09415   tloc = fileloc_createExternal ();
09416   uentry_setDefined (ue, tloc);
09417   fileloc_free (tloc);
09418   uentry_setHasNameError (ue);
09419   
09420   if (context_getFlag (FLG_REPEATUNRECOG))
09421     {
09422       uentry_markOwned (ue);
09423     }
09424   else
09425     {
09426       ue = usymtab_supReturnFileEntry (ue);
09427     }
09428   
09429   if (!context_inMacro ())
09430     {
09431       sRef_clearGlobalScopeSafe ();
09432     }
09433 
09434   return ue;
09435 }
09436 
09437 
09438 
09439 

Generated at Fri Nov 3 18:57:45 2000 for LCLint by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000