]> andersk Git - splint.git/blob - src/uentry.c
Finshed basic merge. Still trying to get it through the test suit.
[splint.git] / src / uentry.c
1 /*
2 ** LCLint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2000 University of Virginia,
4 **         Massachusetts Institute of Technology
5 **
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
10 ** 
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 ** General Public License for more details.
15 ** 
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
19 **
20 ** For information on lclint: lclint-request@cs.virginia.edu
21 ** To report a bug: lclint-bug@cs.virginia.edu
22 ** For more information: http://lclint.cs.virginia.edu
23 */
24 /*
25 ** uentry.c
26 */
27
28 # include "lclintMacros.nf"
29 # include "basic.h"
30 # include "structNames.h"
31 # include "nameChecks.h"
32
33 static /*@dependent@*/ uentry posRedeclared = uentry_undefined;
34 static /*@only@*/ fileloc posLoc = fileloc_undefined;
35 static int nuentries = 0;
36 static int totuentries = 0;
37
38 static void checkGlobalsModifies (/*@notnull@*/ uentry p_ue, sRefSet p_sr) ;
39 static void uentry_setDeclDef (uentry p_e, fileloc p_f) /*@modifies p_e@*/ ;
40 static bool uentry_isRefCounted (uentry p_ue) /*@*/ ;
41 static bool uentry_isRefsField (uentry p_ue) /*@*/ ;
42 static bool uentry_isReallySpecified (uentry p_e) /*@*/ ;
43 static void uentry_checkIterArgs (uentry p_ue);
44 static cstring uentry_dumpAux (uentry p_v, bool p_isParam);
45
46 /*@access ekind@*/
47 static void checkAliasState (/*@notnull@*/ uentry p_old,
48                                /*@notnull@*/ uentry p_unew, 
49                                bool p_mustConform, bool p_completeConform) 
50    /*@modifies p_old, p_unew@*/ ;
51 static void checkNullState (/*@notnull@*/ uentry p_old,
52                             /*@notnull@*/ uentry p_unew, 
53                             bool p_mustConform, bool p_completeConform) 
54    /*@modifies p_old, p_unew@*/ ;
55
56 static void checkVarConformance (/*@notnull@*/ uentry p_old,
57                                  /*@notnull@*/ uentry p_unew, 
58                                  bool p_mustConform, bool p_completeConform) 
59    /*@modifies p_old, p_unew@*/;
60
61 # ifndef NOLCL
62 static void uentry_setHasMods (uentry p_ue) /*@modifies p_ue@*/;
63 static void uentry_setHasGlobs (uentry p_ue) /*@modifies p_ue@*/;
64 # endif
65
66 static void uentry_reallyFree (/*@notnull@*/ /*@only@*/ uentry p_e);
67
68 static void uentry_setSpecDef (/*@special@*/ uentry p_e, /*@keep@*/ fileloc p_f)
69    /*@defines p_e->whereSpecified, p_e->whereDeclared, p_e->whereDefined@*/
70    /*@modifies p_e@*/;
71
72 static void returnValueError (/*@notnull@*/ uentry p_old, /*@notnull@*/ uentry p_unew);
73 static void nargsError (/*@notnull@*/ uentry p_old, /*@notnull@*/ uentry p_unew);
74 static /*@observer@*/ cstring paramStorageName (uentry p_ue) /*@*/ ;
75 static /*@observer@*/ cstring fcnErrName (uentry p_ue) /*@*/ ;
76 static /*@observer@*/ cstring checkedName (chkind p_checked) /*@*/ ;
77 static void 
78   paramTypeError (/*@notnull@*/ uentry p_old, /*@notnull@*/ uentry p_oldCurrent,
79                   ctype p_oldType, /*@notnull@*/ uentry p_unew,
80                   /*@notnull@*/ uentry p_newCurrent, 
81                   ctype p_newType, int p_paramno) /*@modifies g_msgstream@*/ ;
82
83 static /*@only@*/ /*@notnull@*/ uentry 
84   uentry_makeVariableAux (cstring p_n, ctype p_t, /*@keep@*/ fileloc p_f,
85                           /*@exposed@*/ sRef p_s, bool p_priv, vkind p_kind);
86
87 static /*@out@*/ /*@notnull@*/ uentry uentry_alloc (void) /*@*/ 
88 {
89   uentry ue = (uentry) dmalloc (sizeof (*ue));
90   nuentries++;
91   totuentries++;
92   
93   return ue;
94 }
95
96 static cstring uentry_getOptName (uentry p_e) /*@*/ ;
97 static void uentry_copyInto (/*@out@*/ /*@unique@*/ uentry p_unew, uentry p_old);
98 static void uentry_setNullState (/*@notnull@*/ uentry p_ue, nstate p_ns);
99 static void uentry_setAliasKind (/*@notnull@*/ uentry p_ue, alkind p_ak);
100 static /*@only@*/ /*@null@*/ uinfo uinfo_copy (uinfo p_u, ekind p_kind);
101 static void uinfo_free (/*@only@*/ uinfo p_u, ekind p_kind);
102 static void uvinfo_free (/*@only@*/ uvinfo p_u);
103
104 # ifdef DOANNOTS
105
106 static /*@only@*/ cstring ancontext_unparse (ancontext an)
107 {
108   switch (an)
109     {
110     case AN_UNKNOWN: return cstring_makeLiteral ("unknown");
111     case AN_FCNRETURN: return cstring_makeLiteral ("return value");
112     case AN_FCNPARAM: return cstring_makeLiteral ("function param");
113     case AN_SUFIELD: return cstring_makeLiteral ("su field");
114     case AN_TDEFN: return cstring_makeLiteral ("type definition");
115     case AN_GSVAR: return cstring_makeLiteral ("global/static var");
116     case AN_CONST: return cstring_makeLiteral ("constant");
117     BADDEFAULT;
118     }
119   BADEXIT;
120 }
121
122 static int annots[AN_LAST][QU_LAST];
123 static int decls[AN_LAST];
124 static int shdecls[AN_LAST];
125 static int idecls[AN_LAST];
126
127 void initAnnots ()
128 {
129   int i, j;
130
131   for (i = AN_UNKNOWN; i < AN_LAST; i++)
132     {
133       decls[i] = 0;
134       shdecls[i] = 0;
135       idecls[i] = 0;
136
137       for (j = QU_UNKNOWN; j < QU_LAST; j++)
138         {
139           annots[i][j] = 0;
140         }
141     }
142 }
143
144 static void tallyAnnot (ancontext ac, qual q)
145 {
146   (annots[ac][q])++;
147 }
148
149 void printAnnots ()
150 {
151   int total[QU_LAST];
152   int alltotals = 0;
153   int totdecls = 0;
154   int totshdecls = 0;
155   int totidecls = 0;
156   int i, j;
157
158   for (j = QU_UNKNOWN; j < QU_LAST; j++)
159     {
160       total[j] = 0;
161     }
162
163   for (i = AN_UNKNOWN; i < AN_LAST; i++)
164     {
165       int tmptot;
166
167       if (decls[i] > 0)
168         {
169           printf ("Context: %s (%d declarations, %d sharable, %d indirect)\n", 
170                   ancontext_unparse (i),
171                   decls[i], shdecls[i], idecls[i]);
172           
173           totdecls += decls[i];
174           totshdecls += shdecls[i];
175           totidecls += idecls[i];
176           
177           for (j = QU_UNKNOWN; j < QU_LAST; j++)
178             {
179               total[j] += annots[i][j];
180               alltotals += annots[i][j];
181             }
182           
183           printf ("   Allocation:\n");
184           
185           tmptot = 0;
186           
187           for (j = QU_UNKNOWN; j < QU_LAST; j++)
188             {
189               if (qual_isAliasQual (j) && !qual_isUnique (j))
190                 {
191                   if (annots[i][j] > 0)
192                     {
193                       printf ("\t%10s: %5d (%3.2f%%)\n", qual_unparse (j), annots[i][j],
194                               100.0 * (double)annots[i][j] / (double)decls[i]);
195                       tmptot += annots[i][j];
196                     }
197                 }
198             }
199
200           printf ("   Exposure:\n");
201           
202           tmptot = 0;
203           
204           for (j = QU_UNKNOWN; j < QU_LAST; j++)
205             {
206               if (qual_isExQual (j))
207                 {
208                   if (annots[i][j] > 0)
209                     {
210                       printf ("\t%10s: %5d (%3.2f%%)\n", qual_unparse (j), annots[i][j],
211                               100.0 * (double)annots[i][j] / (double)decls[i]);
212                       tmptot += annots[i][j];
213                     }
214                 }
215             }
216           
217           printf ("   Definition:\n");
218           
219           for (j = QU_UNKNOWN; j < QU_LAST; j++)
220             {
221               if (qual_isAllocQual (j))
222                 {
223                   if (annots[i][j] > 0)
224                     {
225                       printf ("\t%10s: %5d (%3.2f%%)\n", qual_unparse (j), annots[i][j],
226                               100.0 * (double)annots[i][j] / (double)decls[i]);
227                     }
228                 }
229             }
230           
231           printf ("   Null:\n");
232           
233           for (j = QU_UNKNOWN; j < QU_LAST; j++)
234             {
235               if (qual_isNull (j) || qual_isNotNull (j) || qual_isRelNull (j))
236                 {
237                   if (annots[i][j] > 0)
238                     {
239                       printf ("\t%10s: %5d (%3.2f%%)\n", qual_unparse (j), annots[i][j],
240                               100.0 * (double)annots[i][j] / (double)decls[i]);
241                     }
242                 }
243             }
244
245           printf ("\n");
246         }
247     }
248
249   for (j = QU_UNKNOWN; j < QU_LAST; j++)
250     {
251       bool hasone = FALSE;
252
253       for (i = AN_UNKNOWN; i < AN_LAST; i++)
254         {
255           if (annots[i][j] > 0)
256             {
257               hasone = TRUE;
258               break;
259             }
260         }
261
262       if (hasone)
263         {
264           printf ("Annotation: %s\n", qual_unparse (j));
265           
266           for (i = AN_UNKNOWN; i < AN_LAST; i++)
267             {
268               if (annots[i][j] > 0)
269                 {
270                   printf ("%25s: %5d\n", ancontext_unparse (i), annots[i][j]);
271                 }
272             }
273           printf ("\n");
274         }
275     }
276
277   printf ("All Contexts\n");
278   
279   for (j = QU_UNKNOWN; j < QU_LAST; j++)
280     {
281       if (total[j] > 0)
282         {
283           printf ("%10s: %5d (%3.2f%%)\n", qual_unparse (j), total[j],
284                   100.0 * (double)total[j] / (double)(totdecls));
285         }
286     }
287   printf ("\n");
288
289   printf ("Total Annotations: %d (%d decls, %d sharable, %d indirect)\n", alltotals, totdecls, totshdecls, totidecls); }
290
291 extern void uentry_tallyAnnots (uentry u, ancontext kind)
292 {
293   alkind ak = sRef_getAliasKind (u->sref);
294   exkind ek = sRef_getExKind (u->sref);
295   nstate ns = sRef_getNullState (u->sref);
296   sstate ss = sRef_getDefState (u->sref);
297   bool recordUnknown = FALSE;
298
299   
300   if (kind == AN_UNKNOWN)
301     {
302       ekind e = u->ukind;
303
304       if (e == KENDITER)
305         {
306           return;
307         }
308       else if (e == KCONST || e == KENUMCONST)
309         {
310           kind = AN_CONST;
311         }
312       else if (e == KFCN || e == KITER)
313         {
314           uentryList params = uentry_getParams (u);
315           bool hasRet = FALSE;
316
317           uentryList_elements (params, current)
318             {
319               if (uentry_isReturned (current))
320                 {
321                   hasRet = TRUE;
322                 }
323               if (!uentry_isElipsisMarker (current))
324                 {
325                   uentry_tallyAnnots (current, AN_FCNPARAM);
326                 }
327             } end_uentryList_elements;
328           
329           kind = AN_FCNRETURN;
330           
331           if (ctype_isFunction (u->utype)
332               && !hasRet
333               && ctype_isVisiblySharable (ctype_realType (ctype_returnValue (u->utype))))
334             {
335               recordUnknown = TRUE;
336             }
337         }
338       else if (e == KDATATYPE || e == KSTRUCTTAG || e == KUNIONTAG || e == KENUMTAG)
339         {
340           ctype t = ctype_realType (u->utype);
341
342           if (ctype_isSU (t))
343             {
344               uentryList fields = ctype_getFields (t);
345
346               uentryList_elements (fields, current)
347                 {
348                   uentry_tallyAnnots (current, AN_SUFIELD);
349                 }
350             } end_uentryList_elements;
351           
352           kind = AN_TDEFN;
353
354           if (ctype_isVisiblySharable (u->utype))
355             {
356               recordUnknown = TRUE;
357             }
358         }
359       else 
360         {
361           kind = AN_GSVAR;
362           
363           
364           if (ctype_isVisiblySharable (ctype_realType (u->utype)))
365             {
366               recordUnknown = TRUE;
367             }
368         }
369     }
370
371   decls[kind]++;
372
373   if (kind == AN_FCNRETURN)
374     {
375       if (recordUnknown) 
376         {
377           shdecls[kind]++;
378           idecls[kind]++;
379         }
380       else 
381         {
382           ;
383         }
384     }
385   else
386     {
387       if (ctype_isVisiblySharable (ctype_realType (u->utype)))
388         {
389           shdecls[kind]++;
390                 }
391       
392       if (ctype_isRealPointer (ctype_realType (u->utype)))
393         {
394           idecls[kind]++;
395         }
396     }
397   
398
399
400
401
402
403
404
405
406
407   switch (ss)
408     {
409     case SS_ALLOCATED: tallyAnnot (kind, QU_OUT); break;
410     case SS_PARTIAL:   tallyAnnot (kind, QU_PARTIAL); break;
411     case SS_RELDEF:    tallyAnnot (kind, QU_RELDEF); break;
412     case SS_SPECIAL:   tallyAnnot (kind, QU_SPECIAL); break;
413     default: break;
414     }
415
416   if (uentry_isReturned (u))
417     {
418       tallyAnnot (kind, QU_RETURNED); 
419     }
420
421   switch (ak)
422     {
423     case AK_UNKNOWN:    
424       if (ctype_isRefCounted (ctype_realType (u->utype))
425           || (ctype_isFunction (u->utype) &&
426               ctype_isRefCounted (ctype_realType (ctype_returnValue (u->utype)))))
427         {
428           ;
429         }
430       else
431         {
432           if (kind == AN_FCNPARAM) 
433             { 
434               tallyAnnot (kind, QU_TEMP); 
435             } 
436           else if (recordUnknown) 
437             { 
438               if (kind == AN_FCNRETURN)
439                 {
440                                 }
441               tallyAnnot (kind, QU_UNKNOWN); 
442             }
443         }
444       break;
445     case AK_ONLY:       tallyAnnot (kind, QU_ONLY); break;
446     case AK_IMPONLY:    tallyAnnot (kind, QU_ONLY); break;
447     case AK_KEEP:       tallyAnnot (kind, QU_KEEP); break;
448     case AK_KEPT:       tallyAnnot (kind, QU_KEPT); break;
449     case AK_IMPTEMP:
450     case AK_TEMP:       tallyAnnot (kind, QU_TEMP); break;
451     case AK_SHARED:     tallyAnnot (kind, QU_SHARED); break;
452     case AK_UNIQUE:     tallyAnnot (kind, QU_UNIQUE); break;
453     case AK_RETURNED:   tallyAnnot (kind, QU_RETURNED); break;
454     case AK_REFCOUNTED: tallyAnnot (kind, QU_UNKNOWN); break;
455     case AK_REFS:       tallyAnnot (kind, QU_REFS); break;
456     case AK_KILLREF:    tallyAnnot (kind, QU_KILLREF); break;
457     case AK_NEWREF:     tallyAnnot (kind, QU_NEWREF); break;
458     case AK_OWNED:      tallyAnnot (kind, QU_OWNED); break;
459     case AK_IMPDEPENDENT:
460     case AK_DEPENDENT:  tallyAnnot (kind, QU_DEPENDENT); break;
461     case AK_ERROR:    
462     case AK_FRESH:
463     case AK_STACK:
464     case AK_LOCAL:
465       break;
466     }
467
468   switch (ek)
469     {
470     case XO_EXPOSED:    tallyAnnot (kind, QU_EXPOSED); break;
471     case XO_OBSERVER:   tallyAnnot (kind, QU_OBSERVER); break;
472     default:  break;
473     }
474
475   switch (ns)
476     {
477     case NS_ERROR:   break;
478     case NS_UNKNOWN:   break;
479     case NS_NOTNULL:   break;
480     case NS_MNOTNULL:  tallyAnnot (kind, QU_NOTNULL); break;
481     case NS_RELNULL:   tallyAnnot (kind, QU_RELNULL); break;
482     case NS_CONSTNULL: tallyAnnot (kind, QU_NULL); break;
483     case NS_POSNULL:   tallyAnnot (kind, QU_NULL); break;
484     case NS_DEFNULL: 
485     case NS_ABSNULL:   break;   
486     }
487 }
488
489 # endif
490
491 static /*@observer@*/ cstring specCode_unparse (specCode s) /*@*/
492 {
493   switch (s)
494     {
495     case SPC_NONE: return cstring_makeLiteralTemp ("normal");
496     case SPC_PRINTFLIKE: return cstring_makeLiteralTemp ("printflike");
497     case SPC_SCANFLIKE: return cstring_makeLiteralTemp ("scanflike");
498     case SPC_MESSAGELIKE: return cstring_makeLiteralTemp ("messagelike");
499     case SPC_LAST: return cstring_makeLiteralTemp ("<error>");
500     }
501
502   BADEXIT;
503 }
504
505 static specCode specCode_fromInt (int i)
506 {
507   /*@+enumint@*/
508   llassert (i >= SPC_NONE && i < SPC_LAST);
509
510   return ((specCode) i);
511   /*@=enumint@*/
512 }
513
514 /*@observer@*/ cstring uentry_specOrDefName (uentry u) 
515 {
516   if (uentry_isDeclared (u))
517     {
518       return cstring_makeLiteralTemp ("previously declared");
519     }
520   else
521     {
522       return cstring_makeLiteralTemp ("specified");
523     }
524 }
525
526 /*@observer@*/ cstring uentry_specDeclName (uentry u) 
527 {
528   if (uentry_isDeclared (u))
529     {
530       return cstring_makeLiteralTemp ("previous declaration");
531     }
532   else
533     {
534       return cstring_makeLiteralTemp ("specification");
535     }
536 }
537
538 static /*@observer@*/ cstring uentry_reDefDecl (uentry old, uentry unew)  /*@*/ 
539 {
540   if (uentry_isCodeDefined (old) && uentry_isCodeDefined (unew))
541     {
542       return cstring_makeLiteralTemp ("redefined");
543     }
544   else if (uentry_isCodeDefined (unew))
545     {
546       return cstring_makeLiteralTemp ("defined");
547     }
548   else if (uentry_isDeclared (old) && uentry_isDeclared (unew))
549     {
550       return cstring_makeLiteralTemp ("redeclared");
551     }
552   else
553     {
554       return cstring_makeLiteralTemp ("declared");
555     }
556 }
557
558 static /*@only@*/ fileloc setLocation (void)
559 {
560   fileloc fl = context_getSaveLocation ();
561
562   if (fileloc_isDefined (fl)) 
563     {
564       return fl;
565     }
566   else
567     {
568       return fileloc_copy (g_currentloc);
569     }
570 }
571
572 /*@notnull@*/ uentry uentry_makeEnumConstant (cstring n, ctype t)
573 {
574   fileloc loc = setLocation ();
575   uentry ue = uentry_makeConstant (n, t, loc);
576
577   ue->ukind = KENUMCONST;
578   uentry_setDefined (ue, loc);
579   return ue;
580 }
581
582 /*@notnull@*/ uentry uentry_makeEnumInitializedConstant (cstring n, ctype t, exprNode expr)
583 {
584   fileloc loc = setLocation ();
585   uentry ue = uentry_makeConstant (n, t, loc);
586   ctype etype = exprNode_getType (expr);
587
588   if (!ctype_isRealInt (etype)) {
589     voptgenerror 
590       (FLG_ENUMMEMBERS,
591        message
592        ("Value of enum member is not an integeral type (type %s): %s",
593         ctype_unparse (etype), exprNode_unparse (expr)),
594        exprNode_loc (expr));
595   }
596   
597   ue->ukind = KENUMCONST;
598   uentry_setDefined (ue, loc);
599   return ue;
600 }
601
602 # ifndef NOLCL
603 /*@notnull@*/ uentry uentry_makeSpecEnumConstant (cstring n, ctype t, fileloc loc)
604 {
605   uentry ue = uentry_makeConstant (n, t, loc);
606
607   ue->ukind = KENUMCONST;
608   return ue;
609 }
610 # endif
611
612 /*@notnull@*/ uentry uentry_makeVariableLoc (cstring n, ctype t)
613 {
614   return uentry_makeVariable (n, t, setLocation (), FALSE);
615 }
616
617 # ifndef NOLCL
618 /*@notnull@*/ /*@only@*/ uentry uentry_makeUnnamedVariable (ctype t)
619 {
620   return uentry_makeVariable (cstring_undefined, t, setLocation (), FALSE);
621 }
622 # endif
623
624 /*@notnull@*/ uentry uentry_makeIdDatatype (idDecl id)
625 {
626   ctype ct = idDecl_getCtype (id);
627   uentry ue = uentry_makeDatatype (idDecl_observeId (id), ct, 
628                                    MAYBE, MAYBE, setLocation ());
629
630   uentry_reflectQualifiers (ue, idDecl_getQuals (id));
631   
632   if (!ynm_isOn (ue->info->datatype->abs))
633     {
634       if (ctype_isUnknown (ct))
635         {
636           ue->info->datatype->mut = MAYBE;
637         }
638       else
639         {
640           ue->info->datatype->mut = ynm_fromBool (ctype_isMutable (ct));
641         }
642     }
643   
644   return ue;
645 }
646
647 void uentry_checkParams (uentry ue)
648 {
649   if (uentry_isValid (ue))
650     {
651       bool isExt = uentry_isExtern (ue);
652
653       if (uentry_isRealFunction (ue))
654         {
655           uentryList params = uentry_getParams (ue);
656
657           uentryList_elements (params, current)
658             {
659               if (uentry_isValid (current))
660                 {
661                   ctype ct = current->utype;                  
662                   
663                   if (ctype_isFixedArray (ct))
664                     {
665                       if (ctype_isArray (ctype_baseArrayPtr (ct))
666                           && !ctype_isFixedArray (ctype_baseArrayPtr (ct)))
667                         {
668                           ;
669                         }
670                       else
671                         {
672                           voptgenerror 
673                             (FLG_FIXEDFORMALARRAY,
674                              message ("Function parameter %q declared as "
675                                       "manifest array (size constant is meaningless)",
676                                       uentry_getName (current)),
677                              uentry_whereDeclared (current));
678                         }
679                     }
680                   else 
681                     {
682                       if (ctype_isArray (ct))
683                         {
684                           voptgenerror 
685                             (FLG_FORMALARRAY,
686                              message ("Function parameter %q declared as "
687                                       "array (treated as pointer)", 
688                                       uentry_getName (current)),
689                              uentry_whereDeclared (current));
690                         }
691                     }
692
693                   if (sRef_getNullState (uentry_getSref (current)) == NS_MNOTNULL)
694                     {
695                       if (ctype_isAbstract (ct) && 
696                           (isExt || (ctype_isAbstract (ctype_realType (ct))
697                                      && !context_hasFileAccess (ctype_typeId (ct)))))
698                         {
699                           vgenhinterror 
700                             (FLG_INCONDEFS,
701                              message 
702                              ("Function %q declared with notnull parameter %q of abstract "
703                               "type %s",
704                               uentry_getName (ue),
705                               uentry_getName (current),
706                               ctype_unparse (ct)),
707                              message 
708                              ("Since %s is an abstract type, notnull can only be "
709                               "used for parameters if the function is static to a "
710                               "module where %s is accessible.",
711                               ctype_unparse (ct),
712                               ctype_unparse (ct)),
713                              uentry_whereDeclared (current));
714                         }
715                     }
716                 }
717             } end_uentryList_elements;
718           
719           if (sRef_getNullState (uentry_getSref (ue)) == NS_MNOTNULL)
720             {
721               ctype ct = ue->utype;
722                   
723               if (ctype_isAbstract (ct) 
724                   && (isExt || (ctype_isAbstract (ctype_realType (ct))
725                                 && !context_hasFileAccess (ctype_typeId (ct)))))
726                 {
727                   vgenhinterror 
728                     (FLG_INCONDEFS,
729                      message 
730                      ("%s %q declared %s notnull storage of abstract type %s",
731                       ekind_capName (uentry_getKind (ue)),
732                       uentry_getName (ue),
733                       fcnErrName (ue),
734                       ctype_unparse (ct)),
735                      message 
736                      ("Since %s is an abstract type, notnull can only be used "
737                       "if it is static to a module where %s is accessible.",
738                       ctype_unparse (ct),
739                       ctype_unparse (ct)),
740                      uentry_whereDeclared (ue));
741                 }
742             }
743         }
744     }
745 }
746
747 static void reflectImplicitFunctionQualifiers (/*@notnull@*/ uentry ue, bool spec)
748 {
749   alkind ak = sRef_getAliasKind (ue->sref);
750
751   if (alkind_isRefCounted (ak))
752     {
753       sRef_setAliasKind (ue->sref, AK_NEWREF, fileloc_undefined);
754     }
755   else 
756     {
757       if (alkind_isUnknown (ak))
758         {
759           exkind ek = sRef_getExKind (ue->sref);
760           
761           if (exkind_isKnown (ek))
762             {
763               sRef_setAliasKind (ue->sref, AK_IMPDEPENDENT, fileloc_undefined);
764             }
765           else 
766             {
767               if (context_getFlag (spec ? FLG_SPECRETIMPONLY : FLG_RETIMPONLY))
768                 {
769                   if (ctype_isVisiblySharable 
770                       (ctype_realType (ctype_returnValue (ue->utype))))
771                     {
772                       if (uentryList_hasReturned (uentry_getParams (ue)))
773                         {
774                           ;
775                         }
776                       else
777                         {
778                           sRef_setAliasKind (ue->sref, AK_IMPONLY, 
779                                              fileloc_undefined);
780                                                 }
781                     }
782                 }
783             }
784         }
785     }
786 }
787
788 static /*@notnull@*/ uentry 
789 uentry_makeFunctionAux (cstring n, ctype t, 
790                         typeIdSet access,
791                         /*@only@*/ globSet globs, 
792                         /*@only@*/ sRefSet mods, 
793                         /*@keep@*/ fileloc f, bool priv,
794                         /*@unused@*/ bool isForward)
795 {
796   uentry e = uentry_alloc ();
797   ctype ret;
798
799   if (ctype_isFunction (t))
800     {
801       ret = ctype_returnValue (t);
802     }
803   else
804     {
805       if (ctype_isKnown (t))
806         {
807           llbug (message ("not function: %s", ctype_unparse (t)));
808         }
809       ret = ctype_unknown;
810     }
811
812   e->ukind = KFCN;
813
814   if (fileloc_isSpec (f) || fileloc_isImport (f))
815     {
816       e->whereSpecified = f;
817       e->whereDeclared = fileloc_undefined;
818     }
819   else
820     {
821       e->whereSpecified = fileloc_undefined;
822       e->whereDeclared = f;
823     }
824
825   /* e->shallowCopy = FALSE; */
826   e->uname = cstring_copy (n);
827   e->utype = t;
828   e->storageclass = SCNONE;
829
830     e->sref = sRef_makeType (ret);
831
832   if (ctype_isUA (ret))
833     {
834       sRef_setStateFromType (e->sref, ret);
835     }
836   
837   e->used = FALSE;
838   e->lset = FALSE;
839   e->uses = filelocList_new ();
840   e->isPrivate = priv;
841   e->hasNameError = FALSE;
842
843   e->info = (uinfo) dmalloc (sizeof (*e->info));
844   e->info->fcn = (ufinfo) dmalloc (sizeof (*e->info->fcn));
845
846   e->info->fcn->hasMods = sRefSet_isDefined (mods);
847   e->info->fcn->hasGlobs = globSet_isDefined (globs);
848
849   e->info->fcn->exitCode = XK_UNKNOWN;
850   e->info->fcn->nullPred = QU_UNKNOWN;
851   e->info->fcn->specialCode = SPC_NONE;
852
853   e->info->fcn->access = access;
854   e->info->fcn->globs = globs;
855   e->info->fcn->defparams = uentryList_undefined;
856
857   sRef_setDefined (e->sref, f);
858   e->whereDefined = fileloc_undefined;
859   
860   e->info->fcn->mods = sRefSet_undefined;
861   e->info->fcn->specclauses = NULL;
862   checkGlobalsModifies (e, mods);
863   e->info->fcn->mods = mods;
864
865   return (e);
866 }
867
868 /*@notnull@*/ uentry uentry_makeIdFunction (idDecl id)
869 {
870   uentry ue = 
871     uentry_makeFunction (idDecl_observeId (id), idDecl_getCtype (id), 
872                          typeId_invalid, globSet_undefined, 
873                          sRefSet_undefined, 
874                          setLocation ());
875   
876   uentry_reflectQualifiers (ue, idDecl_getQuals (id));
877   reflectImplicitFunctionQualifiers (ue, FALSE);
878
879   if (!uentry_isStatic (ue)
880       && cstring_equalLit (ue->uname, "main"))
881     {
882       ctype typ = ue->utype;
883       ctype retval;
884       uentryList args;
885
886       llassert (ctype_isFunction (typ));
887
888       retval = ctype_returnValue (typ);
889
890       if (!ctype_isInt (retval))
891         {
892           voptgenerror 
893             (FLG_MAINTYPE,
894              message ("Function main declared to return %s, should return int",
895                       ctype_unparse (retval)),
896              uentry_whereDeclared (ue));
897         }
898
899       args = ctype_argsFunction (typ);
900
901       if (uentryList_isMissingParams (args) 
902           || uentryList_size (args) == 0)
903         {
904           ;
905         }
906       else
907         {
908           if (uentryList_size (args) != 2)
909             {
910               voptgenerror 
911                 (FLG_MAINTYPE,
912                  message ("Function main declared with %d arg%p, "
913                           "should have 2 (int argc, char *argv[])",
914                           uentryList_size (args)),
915                  uentry_whereLast (ue));
916             }
917           else
918             {
919               uentry arg = uentryList_getN (args, 0);
920               ctype ct = uentry_getType (arg);
921
922               if (!ctype_isInt (ct))
923                 {
924                   voptgenerror 
925                     (FLG_MAINTYPE,
926                      message ("Parameter 1, %q, of function main declared "
927                               "with type %t, should have type int",
928                               uentry_getName (arg), ct),
929                      uentry_whereDeclared (arg));
930                 }
931
932               arg = uentryList_getN (args, 1);
933               ct = uentry_getType (arg);
934
935               if (ctype_isArrayPtr (ct)
936                   && ctype_isArrayPtr (ctype_baseArrayPtr (ct))
937                   && ctype_isChar (ctype_baseArrayPtr (ctype_baseArrayPtr (ct))))
938                 {
939                   ;
940                 }
941               else
942                 {
943                   voptgenerror 
944                     (FLG_MAINTYPE,
945                      message ("Parameter 2, %q, of function main declared "
946                               "with type %t, should have type char **",
947                               uentry_getName (arg), ct),
948                      uentry_whereDeclared (arg));
949                 }
950             }
951         }
952     }
953
954   return ue;
955 }
956
957 static void uentry_implicitParamAnnots (/*@notnull@*/ uentry e)
958 {
959   alkind ak = sRef_getAliasKind (e->sref);
960
961   if ((alkind_isUnknown (ak) || alkind_isImplicit (ak))
962       && context_getFlag (FLG_PARAMIMPTEMP))
963     {
964       exkind ek = sRef_getExKind (e->sref);
965       
966       if (exkind_isKnown (ek))
967         {
968           sRef_setAliasKind (e->sref, AK_IMPDEPENDENT, fileloc_undefined);
969           sRef_setOrigAliasKind (e->sref, AK_IMPDEPENDENT);
970         }
971       else
972         {
973           sRef_setAliasKind (e->sref, AK_IMPTEMP, fileloc_undefined);
974           sRef_setOrigAliasKind (e->sref, AK_IMPTEMP);
975         }
976     }
977 }
978
979 static /*@only@*/ /*@notnull@*/ uentry 
980 uentry_makeVariableParamAux (cstring n, ctype t, sRef s, sstate defstate)
981 {
982   cstring pname = makeParam (n);
983   uentry e = uentry_makeVariableAux (pname, t, setLocation (), s, FALSE, VKPARAM);
984
985   cstring_free (pname);
986   uentry_implicitParamAnnots (e);
987
988   if (!sRef_isAllocated (e->sref) && !sRef_isPartial (e->sref))
989     {
990       sRef_setDefState (e->sref, defstate, uentry_whereDeclared (e));
991       e->info->var->defstate = defstate;
992     }
993
994   return (e);
995 }
996
997 # ifndef NOLCL
998 void
999 uentry_setRefCounted (uentry e)
1000 {
1001   if (uentry_isValid (e))
1002     {
1003       uentry_setAliasKind (e, AK_REFCOUNTED);
1004       sRef_storeState (e->sref);
1005     }
1006 }
1007 # endif
1008
1009 void
1010 uentry_setStatic (uentry c)
1011 {
1012   if (uentry_isValid (c)) 
1013     {
1014       alkind ak = sRef_getAliasKind (c->sref);
1015       c->storageclass = SCSTATIC;
1016
1017       if (uentry_isVariable (c) && !ctype_isFunction (uentry_getType (c)))
1018         {
1019           if (!alkind_isUnknown (ak)
1020               && !alkind_isStatic (ak))
1021             {
1022               if  (!(ctype_isRealPointer (uentry_getType (c)))
1023                    && !(ctype_isAbstract (ctype_realType (uentry_getType (c))))
1024                    && !alkind_isRefCounted (ak))
1025                 {
1026                   if (alkind_isImplicit (ak)
1027                       && alkind_isDependent (ak)
1028                       && ctype_isArray (uentry_getType (c)))
1029                     {
1030                       ; /* no error for observer arrays */
1031                     }
1032                   else
1033                     {
1034                       voptgenerror 
1035                         (FLG_INCONDEFS,
1036                          message ("Static storage %q declared as %s",
1037                                   uentry_getName (c),
1038                                   alkind_unparse (ak)),
1039                          uentry_whereDeclared (c));
1040                     }
1041                 }
1042             }
1043           else
1044             {
1045               if (alkind_isUnknown (ak)
1046                   || (alkind_isImplicit (sRef_getAliasKind (c->sref))
1047                       && !alkind_isDependent (sRef_getAliasKind (c->sref))))
1048                 {
1049                   sRef_setAliasKind (c->sref, AK_STATIC, fileloc_undefined);
1050                   sRef_setOrigAliasKind (c->sref, AK_STATIC);
1051                 }
1052             }
1053         }
1054     }
1055 }
1056
1057 void
1058 uentry_setExtern (uentry c)
1059 {
1060   if (uentry_isValid (c)) 
1061     c->storageclass = SCEXTERN;
1062 }
1063
1064 void
1065 uentry_setParamNo (uentry ue, int pno)
1066 {
1067   llassert (uentry_isAnyParam (ue) && sRef_isParam (ue->sref));
1068   sRef_setParamNo (ue->sref, pno);
1069 }
1070
1071 static
1072 void checkGlobalsModifies (/*@notnull@*/ uentry ue, sRefSet sr)
1073 {
1074   sRefSet_allElements (sr, el)
1075     {
1076       sRef base = sRef_getRootBase (el);
1077       
1078       if (sRef_isGlobal (base) || sRef_isInternalState (base)
1079           || (sRef_isKindSpecial (base) && !sRef_isNothing (base)))
1080         {
1081           if (!globSet_member (ue->info->fcn->globs, base))
1082             {
1083               if (uentry_hasGlobs (ue)
1084                   || context_getFlag (FLG_WARNMISSINGGLOBALSNOGLOBS))
1085                 {
1086                   if (optgenerror 
1087                       (FLG_WARNMISSINGGLOBALS,
1088                        message
1089                        ("Modifies list for %q uses global %q, "
1090                         "not included in globals list.",
1091                         uentry_getName (ue),
1092                         sRef_unparse (base)),
1093                        uentry_whereLast (ue)))
1094                     {
1095                       uentry_showWhereSpecified (ue);
1096                     } 
1097                 }
1098               
1099               ue->info->fcn->globs = globSet_insert (ue->info->fcn->globs, 
1100                                                      base);
1101               if (sRef_isFileStatic (base))
1102                 {
1103                   context_recordFileGlobals (ue->info->fcn->globs);
1104                 }
1105             }
1106         }
1107     } end_sRefSet_allElements;
1108 }
1109
1110 uentry
1111 uentry_makeVariableSrefParam (cstring n, ctype t, sRef s)
1112 {
1113   return (uentry_makeVariableParamAux (n, t, s, SS_UNKNOWN));
1114 }
1115
1116 void
1117 uentry_fixupSref (uentry ue)
1118 {
1119   sRef sr;
1120   
1121   if (uentry_isUndefined (ue) || uentry_isElipsisMarker (ue)) 
1122     {
1123       return;
1124     }
1125   
1126   sr = uentry_getSref (ue);
1127
1128   sRef_resetState (sr);
1129   sRef_clearDerived (sr);
1130   
1131   llassertprint (uentry_isVariable (ue), ("fixing: %s", uentry_unparseFull (ue)));
1132   llassert (sRef_isValid (sr)); 
1133   
1134   if (uentry_isVariable (ue))
1135     {
1136       sRef_setDefState (sr, ue->info->var->defstate, fileloc_undefined);
1137       sRef_setNullState (sr, ue->info->var->nullstate, fileloc_undefined);
1138     }
1139 }
1140
1141 void uentry_setSpecialClauses (uentry ue, specialClauses clauses)
1142 {
1143   llassert (uentry_isFunction (ue));
1144   llassert (!specialClauses_isDefined (ue->info->fcn->specclauses));
1145
1146   ue->info->fcn->specclauses = clauses;
1147   specialClauses_checkAll (ue);
1148 }
1149
1150 /*
1151 ** Used for @modifies@ @endmodifies@ syntax.
1152 **
1153 ** If ue is specified, sr must contain *only*:
1154 **
1155 **      o file static globals
1156 **      o sRef's derived from modifies spec (i.e., more specific than
1157 **        what was specified)
1158 **
1159 ** Otherwise, if sr has modifies it must match sr.
1160 **
1161 ** If it doesn't have modifies, set them to sr.
1162 */
1163
1164 void
1165 uentry_setModifies (uentry ue, /*@owned@*/ sRefSet sr)
1166 {
1167   if (sRef_modInFunction ())
1168     {
1169       llparseerror
1170         (message ("Modifies list not in function context.  "
1171                   "A modifies list can only appear following the parameter list "
1172                   "in a function declaration or header."));
1173
1174       /*@-mustfree@*/ return; /*@=mustfree@*/ 
1175     }
1176
1177   if (sRefSet_hasStatic (sr))
1178     {
1179       context_recordFileModifies (sr);
1180     }
1181
1182   if (uentry_isValid (ue))
1183     {
1184       if (uentry_isIter (ue))
1185         {
1186           llassert (sRefSet_isUndefined (ue->info->iter->mods));
1187           ue->info->iter->mods = sr;
1188         }
1189       else
1190         {
1191           if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue)))
1192             {
1193               uentry_makeVarFunction (ue);
1194             }
1195           
1196           llassertfatal (uentry_isFunction (ue));
1197           llassert (sRefSet_isUndefined (ue->info->fcn->mods));
1198           
1199           ue->info->fcn->mods = sr;
1200           ue->info->fcn->hasMods = TRUE;
1201           
1202           checkGlobalsModifies (ue, sr);
1203         }
1204       
1205       if (context_getFlag (FLG_MODIFIESIMPNOGLOBALS))
1206         {
1207           ue->info->fcn->hasGlobs = TRUE;
1208         }
1209     }
1210   else
1211     {
1212       sRefSet_free (sr);
1213     }
1214 }
1215
1216 /*
1217 ** requires: new and old are functions
1218 */
1219  
1220 static void
1221 checkGlobalsConformance (/*@notnull@*/ uentry old, 
1222                          /*@notnull@*/ uentry unew, 
1223                          bool mustConform, bool completeConform)
1224 {
1225   bool hasInternalState = FALSE;
1226
1227   old->info->fcn->hasGlobs |= unew->info->fcn->hasGlobs;
1228
1229   if (globSet_isDefined (unew->info->fcn->globs))
1230     {
1231       globSet_allElements (unew->info->fcn->globs, el)
1232         {
1233           if (sRef_isFileStatic (el))
1234             {
1235               sRef sr = globSet_lookup (old->info->fcn->globs, el);
1236
1237               if (sRef_isInvalid (sr))
1238                 {
1239                   bool hasError = FALSE;
1240
1241                   if (!hasInternalState 
1242                       && sRef_isInvalid (globSet_lookup (old->info->fcn->globs,
1243                                                          sRef_makeInternalState ()))
1244                       && sRef_isInvalid (globSet_lookup (old->info->fcn->globs,
1245                                                          sRef_makeSpecState ())))
1246                     {
1247                       if (mustConform 
1248                           && !uentry_isStatic (old)
1249                           && optgenerror 
1250                           (FLG_INCONDEFS,
1251                            message ("Globals list for %q includes internal state, %q, "
1252                                     "but %s without globals internalState.",
1253                                     uentry_getName (old),
1254                                     sRef_unparse (el),
1255                                     uentry_specOrDefName (old)),
1256                            uentry_whereLast (unew)))
1257                         {
1258                           uentry_showWhereSpecified (old);
1259                           hasError = TRUE;
1260                         }
1261                       
1262                       old->info->fcn->globs = globSet_insert (old->info->fcn->globs,
1263                                                               sRef_makeInternalState ());
1264                       hasInternalState = TRUE;
1265                     }
1266
1267                   if (!hasError
1268                       && fileloc_sameFile (uentry_whereDeclared (unew),
1269                                            uentry_whereDeclared (old)))
1270                     {
1271                       if (mustConform
1272                           && optgenerror 
1273                           (FLG_INCONDEFS,
1274                            message ("Function %q inconsistently %rdeclared (in "
1275                                     "same file) with file static global %q in "
1276                                     "globals list",
1277                                     uentry_getName (unew),
1278                                     uentry_isDeclared (old),
1279                                     sRef_unparse (el)),
1280                            uentry_whereDeclared (unew)))
1281                         {
1282                           uentry_showWhereSpecified (old);
1283                         }
1284                     }
1285                 }
1286
1287               old->info->fcn->globs = globSet_insert (old->info->fcn->globs, el);
1288               context_recordFileGlobals (old->info->fcn->globs);
1289             }
1290           else
1291             {
1292               sRef sr = globSet_lookup (old->info->fcn->globs, el);
1293               
1294               if (sRef_isInvalid (sr))
1295                 {
1296                   if (mustConform
1297                       && optgenerror 
1298                       (FLG_INCONDEFS,
1299                        message ("Function %q inconsistently %rdeclared with "
1300                                 "%q in globals list",
1301                                 uentry_getName (unew),
1302                                 uentry_isDeclared (old),
1303                                 sRef_unparse (el)),
1304                        uentry_whereDeclared (unew)))
1305                     {
1306                       old->info->fcn->globs = globSet_insert (old->info->fcn->globs, el);
1307                       uentry_showWhereSpecified (old);
1308                     }
1309                 }
1310               else
1311                 {
1312                   if (!bool_equal (sRef_isAllocated (el), sRef_isAllocated (sr)))
1313                     {
1314                       if (mustConform
1315                           && optgenerror 
1316                           (FLG_INCONDEFS,
1317                            message 
1318                            ("Function %q global %q inconsistently "
1319                             "%rdeclared as %qout global",
1320                             uentry_getName (unew),
1321                             sRef_unparse (el),
1322                             uentry_isDeclared (old),
1323                             cstring_makeLiteral (sRef_isAllocated (el) ? "" : "non-")),
1324                            uentry_whereDeclared (unew)))
1325                         {
1326                           uentry_showWhereSpecified (old);
1327                         }
1328                     }
1329                 }
1330             }
1331         } end_globSet_allElements ;
1332
1333       if (completeConform)
1334         {
1335           globSet_allElements (old->info->fcn->globs, el)
1336             {
1337               sRef sr = globSet_lookup (unew->info->fcn->globs, el);
1338               
1339               if (sRef_isInvalid (sr))
1340                 {
1341                   if (mustConform
1342                       && uentry_isReallySpecified (old)
1343                       && optgenerror 
1344                       (FLG_NEEDSPEC,
1345                        message ("Function %q specified with %q in globals list, "
1346                                 "but declared without %q",
1347                                 uentry_getName (unew),
1348                                 sRef_unparse (el),
1349                                 sRef_unparse (el)),
1350                        uentry_whereDeclared (unew)))
1351                     {
1352                       uentry_showWhereSpecified (old);
1353                     }
1354                 }
1355             } end_globSet_allElements;
1356         }
1357     }
1358   else
1359     {
1360       if (completeConform && !globSet_isEmpty (old->info->fcn->globs))
1361         {
1362           if (uentry_isReallySpecified (old)
1363               && optgenerror 
1364               (FLG_NEEDSPEC,
1365                message ("%s %q specified with globals list, but "
1366                         "declared with no globals",
1367                         ekind_capName (unew->ukind),
1368                         uentry_getName (unew)),
1369                uentry_whereDeclared (unew)))
1370             {
1371               llgenindentmsg 
1372                 (message ("Specification globals: %q", 
1373                           globSet_unparse (old->info->fcn->globs)),
1374                  uentry_whereSpecified (old));
1375             }
1376         }
1377       
1378       unew->info->fcn->globs = globSet_copy (unew->info->fcn->globs, 
1379                                             old->info->fcn->globs);
1380     }
1381 }
1382
1383 /*
1384 ** new modifies list must be included by old modifies list.
1385 **
1386 ** file static state may be added to new, if old has internal.
1387 */
1388
1389 static void
1390 checkModifiesConformance (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew, 
1391                           bool mustConform, bool completeConform)
1392 {
1393   sRefSet newMods;
1394   bool changedMods = FALSE;
1395   bool modInternal = FALSE;
1396
1397   llassert (uentry_isFunction (old) && uentry_isFunction (unew));
1398
1399   old->info->fcn->hasMods |= unew->info->fcn->hasMods;
1400   newMods = unew->info->fcn->mods;
1401             
1402   if (sRefSet_isEmpty (newMods))
1403     {
1404       if (completeConform && !sRefSet_isEmpty (old->info->fcn->mods)
1405           && uentry_isReallySpecified (old))
1406         {
1407           if (optgenerror 
1408               (FLG_NEEDSPEC,
1409                message ("%s %q specified with modifies clause, "
1410                         "but declared with no modifies clause",
1411                         ekind_capName (unew->ukind),
1412                         uentry_getName (unew)),
1413                uentry_whereDeclared (unew)))
1414             {
1415               llgenindentmsg (message ("Specification has modifies %q", 
1416                                        sRefSet_unparse (old->info->fcn->mods)),
1417                               uentry_whereSpecified (old));
1418             }
1419         }
1420
1421       return;
1422     }
1423
1424   sRefSet_allElements (newMods, current)
1425     {
1426       if (sRef_isValid (current))
1427         {
1428           sRef rb = sRef_getRootBase (current);
1429           
1430           if (sRef_isFileStatic (rb))
1431             {
1432               if (!modInternal)
1433                 {
1434                   if (!sRefSet_isSameMember (old->info->fcn->mods, 
1435                                              sRef_makeInternalState ())
1436                       && !sRefSet_isSameMember (old->info->fcn->mods, 
1437                                                 sRef_makeSpecState ()))
1438                     {
1439                       if (mustConform 
1440                           && !uentry_isStatic (old)
1441                           && optgenerror 
1442                           (FLG_INCONDEFS,
1443                            message
1444                            ("Modifies list for %q includes internal state, "
1445                             "but %s without modifies internal.",
1446                             uentry_getName (old),
1447                             uentry_specOrDefName (old)),
1448                            uentry_whereLast (unew)))
1449                         {
1450                           uentry_showWhereSpecified (old);
1451                         }
1452                       
1453                       old->info->fcn->mods = 
1454                         sRefSet_insert (old->info->fcn->mods, 
1455                                         sRef_makeInternalState ());
1456                       modInternal = TRUE;
1457                     }
1458                 }
1459               
1460               old->info->fcn->mods = sRefSet_insert (old->info->fcn->mods,
1461                                                      current);
1462               changedMods = TRUE;
1463             }
1464           else
1465             {
1466               if (sRef_canModifyVal (current, old->info->fcn->mods))
1467                 {
1468                   int size = sRefSet_size (old->info->fcn->mods);
1469
1470                   old->info->fcn->mods = sRefSet_insert (old->info->fcn->mods,
1471                                                          current);
1472
1473                   if (sRefSet_size (old->info->fcn->mods) != size)
1474                     {
1475                       changedMods = TRUE;
1476                     }
1477                 }
1478               else
1479                 {
1480                   if (mustConform
1481                       && optgenerror 
1482                       (FLG_INCONDEFS,
1483                        message 
1484                        ("Modifies list for %q contains %q, not modifiable "
1485                         "according to %s",
1486                         uentry_getName (old),
1487                         sRef_unparse (current),
1488                         uentry_specDeclName (old)),
1489                        uentry_whereLast (unew)))
1490                     {
1491                       uentry_showWhereSpecified (old);
1492                     }
1493                 }
1494             }
1495         }
1496     } end_sRefSet_allElements;
1497
1498   if (completeConform && uentry_isReallySpecified (old))
1499     {
1500       sRefSet_allElements (old->info->fcn->mods, el)
1501         {
1502           if (sRef_canModify (el, newMods))
1503             {
1504               ; /* okay */
1505             }
1506           else
1507             {
1508               if (optgenerror 
1509                   (FLG_NEEDSPEC,
1510                    message 
1511                    ("Specification modifies clause for %q contains %q, "
1512                     "not included in declaration modifies clause",
1513                     uentry_getName (old),
1514                     sRef_unparse (el)),
1515                    uentry_whereLast (unew)))
1516                 {
1517                   uentry_showWhereSpecified (old);
1518                 }
1519             }
1520         } end_sRefSet_allElements ;
1521     } 
1522
1523   /*
1524   ** Make sure file static elements will be removed.
1525   */
1526
1527   if (changedMods)
1528     {
1529       context_recordFileModifies (old->info->fcn->mods);
1530     }
1531 }
1532
1533 static void 
1534   uentry_checkMutableType (uentry ue)
1535 {
1536   ctype ct = uentry_getType (ue);
1537
1538   if (!ctype_isRealPointer (ct) && !ctype_isRealAbstract (ct))
1539     {
1540       voptgenerror (FLG_MUTREP,
1541                     message ("Mutable abstract type %q declared without pointer "
1542                              "indirection: %t (violates assignment semantics)",
1543                              uentry_getName (ue), ct),
1544                     uentry_whereDeclared (ue));
1545     }
1546 }
1547
1548 void
1549 uentry_setMutable (uentry e)
1550 {
1551   llassert (uentry_isDatatype (e));
1552   e->info->datatype->mut = YES;
1553 }
1554
1555 static void
1556 uentry_checkIterArgs (uentry ue)
1557 {
1558   bool hasYield = FALSE;
1559   uentryList args;
1560
1561   llassert (uentry_isIter (ue));
1562
1563   args = uentry_getParams (ue);
1564
1565   uentryList_elements (args, el)
1566     {
1567       sstate ds = uentry_getDefState (el);
1568
1569       if (uentry_isYield (el))
1570         {
1571           hasYield = TRUE;
1572         }
1573
1574       if (sstate_isUnknown (ds))
1575         {
1576           uentry_setDefState (el, SS_DEFINED);
1577         }
1578       else
1579         {
1580           ;
1581         }
1582     } end_uentryList_elements;
1583
1584   if (!hasYield)
1585     {
1586       voptgenerror (FLG_HASYIELD,
1587                     message ("Iterator %q declared with no yield parameters",
1588                              uentry_getName (ue)),
1589                     uentry_whereDeclared (ue));
1590     }
1591 }
1592
1593 static chkind
1594 chkind_fromQual (qual qel)
1595 {
1596   if (qual_isChecked (qel))
1597     {
1598       return CH_CHECKED;
1599     }
1600   else if (qual_isCheckMod (qel))
1601     {
1602       return CH_CHECKMOD;
1603     }
1604   else if (qual_isCheckedStrict (qel))
1605     {
1606       return CH_CHECKEDSTRICT;
1607     }
1608   else if (qual_isUnchecked (qel))
1609     {
1610       return CH_UNCHECKED;
1611     }
1612   else
1613     {
1614       BADEXIT;
1615       /*@notreached@*/ return CH_UNKNOWN;
1616     }
1617 }
1618
1619 static void
1620 uentry_reflectOtherQualifier (/*@notnull@*/ uentry ue, qual qel)
1621 {
1622   if (qual_isKillRef (qel) || qual_isNewRef (qel) || qual_isTempRef (qel))
1623     {
1624       if (!uentry_isRefCounted (ue))
1625         {
1626           llerror 
1627             (FLG_SYNTAX, 
1628              message ("Reference counting qualifier %s used on non-reference "
1629                       "counted storage: %q",
1630                       qual_unparse (qel), 
1631                       uentry_unparse (ue)));
1632         }
1633       else
1634         {
1635           alkind ak = alkind_fromQual (qel);
1636           
1637           uentry_setAliasKind (ue, ak);
1638         }
1639     }
1640   else if (qual_isRefCounted (qel))
1641     {
1642       ctype ct = ctype_realType (uentry_getType (ue));
1643       ctype rt;
1644       
1645       if (ctype_isPointer (ct) 
1646           && (ctype_isStruct (rt = ctype_realType (ctype_baseArrayPtr (ct)))))
1647         {
1648           /* check there is a refs field */
1649           uentryList fields = ctype_getFields (rt);
1650           uentry refs = uentry_undefined;
1651
1652           uentryList_elements (fields, field)
1653             {
1654               if (uentry_isRefsField (field))
1655                 {
1656                   if (uentry_isValid (refs))
1657                     {
1658                       llerror 
1659                         (FLG_SYNTAX, 
1660                          message ("Reference counted structure type %s has "
1661                                   "multiple refs fields: %q and %q",
1662                                   ctype_unparse (ct),
1663                                   uentry_getName (refs),
1664                                   uentry_getName (field)));
1665                     }
1666                   
1667                   refs = field;
1668                 }
1669             } end_uentryList_elements;
1670
1671           if (uentry_isInvalid (refs))
1672             {
1673               vgenhinterror 
1674                 (FLG_SYNTAX, 
1675                  message ("Reference counted structure type %s has "
1676                           "no refs field",
1677                           ctype_unparse (ct)),
1678                  cstring_makeLiteral
1679                  ("To count reference, the structure must have a field named "
1680                   "refs of type int."),
1681                  g_currentloc);           
1682             }
1683           else if (!ctype_isInt (uentry_getType (refs)))
1684             {
1685               llerror 
1686                 (FLG_SYNTAX, 
1687                  message ("Reference counted structure type %s refs field has "
1688                           "type %s (should be int)", ctype_unparse (ct),
1689                           ctype_unparse (uentry_getType (refs))));
1690             }
1691           else
1692             {
1693               sRef_setAliasKind (ue->sref, alkind_fromQual (qel), 
1694                                  uentry_whereDeclared (ue));
1695             }
1696         }
1697       else
1698         {
1699           if ((ctype_isPointer (ct) 
1700                && ctype_isUnknown (ctype_realType (ctype_baseArrayPtr (ct))))
1701               ||ctype_isAbstract (ct) || ctype_isUnknown (ct))
1702             {
1703               sRef_setAliasKind (ue->sref, alkind_fromQual (qel), 
1704                                  uentry_whereDeclared (ue));
1705             }
1706           else
1707             {
1708               llerror 
1709                 (FLG_SYNTAX, 
1710                  message ("Non-pointer to structure type %s declared with "
1711                           "refcounted qualifier",
1712                           ctype_unparse (ct)));
1713             }
1714         }
1715     }
1716   else if (qual_isRefs (qel))
1717     {
1718       if (uentry_isVariable (ue) && !uentry_isParam (ue))
1719         {
1720           uentry_setAliasKind (ue, AK_REFS);
1721         }
1722       else
1723         {
1724           llerror 
1725             (FLG_SYNTAX, 
1726              message ("Refs qualifier used on non-structure field: %q",
1727                       uentry_unparse (ue)));
1728         }
1729     }
1730   else if (qual_isAliasQual (qel))
1731     {
1732       alkind ak = alkind_fromQual (qel);
1733       bool okay = TRUE;
1734       alkind oldak = uentry_getAliasKind (ue);
1735       ctype ut = uentry_getType (ue);
1736       
1737       if (alkind_isImplicit (ak) 
1738           && (alkind_isKnown (oldak) && !alkind_isImplicit (oldak)))
1739         {
1740           /* ignore the implied qualifier */
1741           okay = FALSE;
1742         }
1743       
1744       if (uentry_isEitherConstant (ue))
1745         {
1746           llerror 
1747             (FLG_SYNTAX, 
1748              message ("Alias qualifier %s used on constant: %q",
1749                       alkind_unparse (ak), uentry_unparse (ue)));
1750           okay = FALSE;
1751         }
1752       
1753       if (ctype_isFunction (ut))
1754         {
1755           ut = ctype_returnValue (ut);
1756         }
1757       
1758       if (!(ctype_isVisiblySharable (ut) 
1759             || ctype_isRealArray (ut)
1760             || ctype_isRealSU (ut)))
1761         {
1762           if (!qual_isImplied (qel))
1763             {
1764               llerror 
1765                 (FLG_SYNTAX, 
1766                  message ("Alias qualifier %s used on unsharable storage type %t: %q",
1767                           alkind_unparse (ak), ut, uentry_getName (ue)));
1768             }
1769           
1770           okay = FALSE;
1771         }
1772       else
1773         {
1774           if (uentry_isRefCounted (ue))
1775             {
1776               if (!(qual_isRefQual (qel) || qual_isOnly (qel)
1777                     || qual_isExposed (qel) 
1778                     || qual_isObserver (qel)))
1779                 {
1780                   if (!qual_isImplied (qel))
1781                     {
1782                       llerror 
1783                         (FLG_SYNTAX, 
1784                          message 
1785                          ("Alias qualifier %s used on reference counted storage: %q",
1786                           alkind_unparse (ak), 
1787                           uentry_unparse (ue)));
1788                     }
1789                   
1790                   okay = FALSE;
1791                 }
1792             }
1793           else
1794             {
1795               if (qual_isRefQual (qel))
1796                 {
1797                   llerror 
1798                     (FLG_SYNTAX, 
1799                      message ("Qualifier %s used on non-reference counted storage: %q",
1800                               alkind_unparse (ak), uentry_unparse (ue)));
1801                   
1802                   okay = FALSE;
1803                 }
1804             }
1805         }
1806       
1807       if (okay)
1808         {
1809           uentry_setAliasKind (ue, ak);
1810         }
1811     }
1812   else if (qual_isNull (qel))
1813     {
1814       if (uentry_isConstant (ue))
1815         {
1816           sRef_setNullState 
1817             (ue->sref, 
1818              ctype_isAbstract (ue->utype) ? NS_CONSTNULL : NS_DEFNULL, 
1819              uentry_whereDeclared (ue));
1820         }
1821       else
1822         {
1823           uentry_setNullState (ue, NS_POSNULL);
1824         }
1825     }
1826   else if (qual_isRelNull (qel))
1827     {
1828       uentry_setNullState (ue, NS_RELNULL);
1829     }
1830   else if (qual_isNotNull (qel))
1831     {
1832       uentry_setNullState (ue, NS_MNOTNULL);
1833     }
1834   else if (qual_isAbstract (qel)
1835            || qual_isConcrete (qel))
1836     {
1837       if (!uentry_isDatatype (ue))
1838         {
1839           llerror 
1840             (FLG_SYNTAX, 
1841              message ("Qualifier %s used with non-datatype", 
1842                       qual_unparse (qel)));
1843         }
1844       else
1845         {
1846           ue->info->datatype->abs = ynm_fromBool (qual_isAbstract (qel));
1847         }
1848     }
1849   else if (qual_isMutable (qel))
1850     {
1851       if (!uentry_isDatatype (ue))
1852         {
1853           llerror (FLG_SYNTAX,
1854                    message ("Qualifier %s used with non-datatype", qual_unparse (qel)));
1855         }
1856       else
1857         {
1858           if (!ynm_isOn (ue->info->datatype->mut))
1859             {
1860               uentry_checkMutableType (ue);
1861             }
1862           
1863           ue->info->datatype->mut = YES;
1864         }
1865     }
1866   else if (qual_isImmutable (qel))
1867     {
1868       if (!uentry_isDatatype (ue))
1869         {
1870           llerror (FLG_SYNTAX, message ("Qualifier %s used with non-datatype", 
1871                                         qual_unparse (qel)));
1872         }
1873       else
1874         {
1875           ue->info->datatype->mut = NO;
1876         }
1877     }
1878   else if (qual_isNullPred (qel))
1879     {
1880       if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue)))
1881         {
1882           uentry_makeVarFunction (ue);
1883         }
1884       
1885       if (uentry_isFunction (ue))
1886         {
1887           ctype typ = uentry_getType (ue);
1888           ctype rtype = ctype_returnValue (uentry_getType (ue));
1889           
1890           if (ctype_isRealBool (rtype))
1891             {
1892               uentryList pl = ctype_argsFunction (typ);
1893               
1894               if (uentryList_size (pl) == 1)
1895                 {
1896                   ue->info->fcn->nullPred = qel;
1897                 }
1898               else
1899                 {
1900                   llerror (FLG_SYNTAX, 
1901                            message ("Qualifier %s used with function having %d "
1902                                     "arguments (should have 1)", 
1903                                     qual_unparse (qel),
1904                                     uentryList_size (pl)));
1905                 }
1906             }
1907           else
1908             {
1909               llerror (FLG_SYNTAX, 
1910                        message ("Qualifier %s used with function returning %s "
1911                                 "(should return bool)", 
1912                                 qual_unparse (qel),
1913                                 ctype_unparse (rtype)));
1914             }
1915         }
1916       else
1917         {
1918           llerror (FLG_SYNTAX, 
1919                    message ("Qualifier %s used with non-function", 
1920                             qual_unparse (qel)));
1921         }
1922     }
1923   else if (qual_isExitQual (qel))
1924     {
1925       exitkind exk = exitkind_fromQual (qel);
1926       
1927       if (uentry_isFunction (ue))
1928         {
1929           if (exitkind_isKnown (ue->info->fcn->exitCode))
1930             {
1931               llerror (FLG_SYNTAX, 
1932                        message ("Multiple exit qualifiers used on function %q:  %s, %s", 
1933                                 uentry_getName (ue),
1934                                 exitkind_unparse (ue->info->fcn->exitCode),
1935                                 exitkind_unparse (exk)));
1936             }
1937           
1938           ue->info->fcn->exitCode = exk;
1939         }
1940       else
1941         {
1942           if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue)))
1943             {
1944               uentry_makeVarFunction (ue);
1945               ue->info->fcn->exitCode = exk;
1946             }
1947           else
1948             {
1949               llerror (FLG_SYNTAX,
1950                        message ("Exit qualifier %s used with non-function (type %s)", 
1951                                 qual_unparse (qel),
1952                                 ctype_unparse (uentry_getType (ue))));
1953             }
1954         }
1955     }
1956   else
1957     {
1958       if (qual_isCQual (qel))
1959         {
1960           ; /* okay */
1961         }
1962       else
1963         {
1964           llbug (message ("unhandled qualifier: %s", qual_unparse (qel)));
1965         }
1966     }
1967 }
1968
1969 void
1970 uentry_reflectQualifiers (uentry ue, qualList q)
1971 {
1972   llassert (uentry_isValid (ue)); 
1973
1974   qualList_elements (q, qel)
1975     {
1976       if (qual_isStatic (qel))
1977         {
1978           uentry_setStatic (ue);
1979         }
1980       else if (qual_isUnused (qel))
1981         {
1982           uentry_setUsed (ue, fileloc_undefined);         
1983         }
1984       else if (qual_isExternal (qel))
1985         {
1986           fileloc_free (ue->whereDefined);
1987           ue->whereDefined = fileloc_createExternal ();
1988         }
1989       else if (qual_isSef (qel))
1990         {
1991           if (uentry_isVariable (ue))
1992             {
1993               vkind vk = ue->info->var->kind;
1994
1995               llassert (vk != VKREFPARAM);
1996
1997               if (vk == VKYIELDPARAM)
1998                 {
1999                   llerror
2000                     (FLG_SYNTAX,
2001                      message ("Qualifier sef cannot be used with %s: %q",
2002                               cstring_makeLiteralTemp (vk == VKYIELDPARAM ? "yield" : "returned"),
2003                               uentry_unparse (ue)));
2004                 }
2005               else if (vk == VKRETPARAM)
2006                 {
2007                   ue->info->var->kind = VKSEFRETPARAM;
2008                 }
2009               else
2010                 {
2011                   ue->info->var->kind = VKSEFPARAM;
2012                 }
2013             }
2014           else
2015             {
2016               llerror 
2017                 (FLG_SYNTAX,
2018                  message ("Qualifier sef is meaningful only on parameters: %q", 
2019                           uentry_unparse (ue)));
2020             }
2021         }
2022       else if (qual_isExtern (qel))
2023         {
2024           ue->storageclass = SCEXTERN;
2025         }
2026       else if (qual_isGlobalQual (qel)) /* undef, killed */
2027         {
2028           if (uentry_isVariable (ue))
2029             {
2030               sstate oldstate = ue->info->var->defstate;
2031               sstate defstate = sstate_fromQual (qel);
2032
2033
2034               if ((oldstate == SS_UNDEFGLOB && defstate == SS_KILLED)
2035                   || (oldstate == SS_KILLED && defstate == SS_UNDEFGLOB))
2036                 {
2037                   defstate = SS_UNDEFKILLED;
2038                 }
2039               else 
2040                 {
2041                   ; /* any errors? */
2042                 }
2043
2044               sRef_setDefState (ue->sref, defstate, fileloc_undefined);
2045               ue->info->var->defstate = defstate;
2046             }
2047           else
2048             {
2049               llerror 
2050                 (FLG_SYNTAX, 
2051                  message ("Qualifier %s used on non-variable: %q",
2052                           qual_unparse (qel), uentry_unparse (ue)));          
2053             }
2054         }
2055       /* start modifications */
2056
2057       else if( qual_isBufQualifier(qel) ) {
2058         ctype ct = ctype_realType(uentry_getType(ue));
2059
2060         if( ctype_isArray(ct) || ctype_isPointer(ct) ) {
2061
2062             if( uentry_hasBufStateInfo(ue) )  {
2063
2064                 if( qual_isNullTerminated(qel) ) {  /* handle Nullterm */
2065                     
2066                    if (uentry_isAnyParam(ue) || uentry_isReturned (ue)) {
2067                                                /* If formal func param */
2068                        uentry_setNullTerminatedState(ue); 
2069                        uentry_setLen (ue, 1);
2070                        uentry_setSize (ue, 1);
2071
2072                        sRef_setNullTerminatedState(uentry_getSref(ue));
2073                        sRef_setLen (uentry_getSref(ue), 1);
2074                        sRef_setSize (uentry_getSref(ue), 1);
2075                    } else {
2076                        uentry_setPossiblyNullTerminatedState(ue); 
2077
2078                        sRef_setPossiblyNullTerminatedState(uentry_getSref(ue));
2079                    }
2080
2081                 } 
2082                 /* put other BufState Qualifiers here */
2083             } else { 
2084               llfatalbug(message("INTERNAL Error: we have a NULL BufState \
2085                         struct for identifier %s\n", uentry_getName(ue) ) );
2086             }
2087          } else if (ctype_isFunction (ct)) { /* We have to handle function */
2088
2089             sRef retSref = uentry_getSref (ue);
2090             ctype retType = sRef_getType (retSref);
2091
2092             if (ctype_isPointer (retType) || ctype_isArray (retType)) {
2093                sRef_setNullTerminatedState (retSref);
2094
2095             } else {
2096               
2097                 llerror 
2098                   (FLG_SYNTAX,
2099                        message ("Qualifier %s used on non-pointer on \
2100                             function return: %q", qual_unparse (qel),
2101                                                     uentry_unparse (ue)));
2102              }
2103          }
2104               
2105          else  {
2106                 llerror 
2107                   (FLG_SYNTAX,
2108                        message ("Qualifier %s used on non-pointer: %q",
2109                           qual_unparse (qel), uentry_unparse (ue)));          
2110          }
2111       }/* end else if */    
2112       else if (qual_isAllocQual (qel)) /* out, partial, reldef, special, etc. */
2113         {
2114           ctype realType = ctype_realType (ue->utype);
2115           sstate defstate = sstate_fromQual (qel);
2116
2117           if (ctype_isFunction (realType))
2118             {
2119               realType = ctype_realType (ctype_returnValue (realType));
2120             }
2121
2122           if (qual_isRelDef (qel))
2123             {
2124               ; /* okay anywhere */
2125             }
2126           else
2127             {
2128               if (!ctype_isAP (realType) 
2129                   && !ctype_isSU (realType)
2130                   && !ctype_isUnknown (realType)
2131                   && !ctype_isAbstract (ue->utype))
2132                 {
2133                   llerror 
2134                     (FLG_SYNTAX, 
2135                      message ("Qualifier %s used on non-pointer or struct: %q",
2136                               qual_unparse (qel), uentry_unparse (ue)));
2137                 }
2138             }
2139
2140           uentry_setDefState (ue, defstate);
2141
2142           if (sRef_isStateSpecial (ue->sref)
2143               && alkind_isImplicit (sRef_getAliasKind (ue->sref)))
2144             {
2145               sRef_setAliasKind (ue->sref, AK_ERROR, fileloc_undefined);
2146             }
2147         }
2148       else if (qual_isYield (qel))
2149         {
2150           if (uentry_isVariable (ue))
2151             {
2152               ue->info->var->kind = VKYIELDPARAM;
2153             }
2154           else
2155             {
2156               llerror 
2157                 (FLG_SYNTAX, 
2158                  message ("Qualifier %s used on non-iterator parameter: %q",
2159                           qual_unparse (qel), uentry_unparse (ue)));          
2160             }
2161         }
2162       else if (qual_isExQual (qel))
2163         {
2164           exkind ek = exkind_fromQual (qel);
2165           ctype ut = uentry_getType (ue);
2166
2167           if (ctype_isFunction (ut))
2168             {
2169               ut = ctype_returnValue (ut);
2170             }
2171           
2172           if (!(ctype_isVisiblySharable (ut))
2173               && !(ctype_isArray (ut)) /* can apply to arrays also! */
2174               && !(ctype_isStruct (ctype_realType (ut)))) /* applies to structure fields! */
2175             {
2176               if (!qual_isImplied (qel))
2177                 {
2178                   llerror 
2179                     (FLG_SYNTAX, 
2180                      message ("Qualifier %s used on unsharable storage type %t: %q",
2181                               exkind_unparse (ek), ut, uentry_getName (ue)));
2182                 }
2183             }
2184           else
2185             {
2186               alkind ak = sRef_getAliasKind (ue->sref);
2187
2188               sRef_setExKind (ue->sref, ek, uentry_whereDeclared (ue));
2189
2190               if (alkind_isUnknown (ak) || alkind_isImplicit (ak) || alkind_isStatic (ak))
2191                 {
2192                   if (!alkind_isTemp (ak))
2193                     {
2194                       uentry_setAliasKind (ue, AK_IMPDEPENDENT);
2195                     }
2196                 }
2197               else if (alkind_isDependent (ak) || alkind_isTemp (ak)
2198                        || alkind_isOwned (ak))
2199                 {
2200                   ; /* okay */
2201                 }
2202               else
2203                 {
2204                   llerror 
2205                     (FLG_SYNTAX, 
2206                      message ("Exposure qualifier %s used on %s storage (should "
2207                               "be dependent): %q",
2208                               qual_unparse (qel), 
2209                               alkind_unparse (ak),
2210                               uentry_unparse (ue)));
2211                 }
2212             }
2213         }
2214       else if (qual_isGlobCheck (qel))
2215         {
2216           if (uentry_isVariable (ue))
2217             {
2218               chkind ch = chkind_fromQual (qel);                
2219                        
2220               if (ue->info->var->checked != CH_UNKNOWN)
2221                 {
2222                   if (ch == ue->info->var->checked)
2223                     {
2224                       llerror (FLG_SYNTAX, 
2225                                message ("Redundant %s qualifier on %q",
2226                                         qual_unparse (qel),
2227                                         uentry_getName (ue)));
2228                     }
2229                   else
2230                     {
2231                       llerror (FLG_SYNTAX, 
2232                                message
2233                                ("Contradictory %s and %s qualifiers on %q",
2234                                 qual_unparse (qel),
2235                                 checkedName (ue->info->var->checked),
2236                                 uentry_getName (ue)));
2237                     }
2238                 }
2239
2240               ue->info->var->checked = ch;
2241             }
2242           else
2243             {
2244               llerror
2245                 (FLG_SYNTAX, 
2246                  message ("Qualifier %s used with non-variable", 
2247                           qual_unparse (qel)));
2248             }
2249         }
2250       else if (qual_isReturned (qel))
2251         {
2252           if (uentry_isVariable (ue))
2253             {
2254               ue->info->var->kind = VKRETPARAM;
2255             }
2256           else
2257             {
2258               llerror (FLG_SYNTAX, message ("Qualifier %s used with non-variable", 
2259                                             qual_unparse (qel)));
2260             }
2261         }
2262       else
2263         {
2264           uentry_reflectOtherQualifier (ue, qel);
2265         }
2266
2267       sRef_storeState (ue->sref);
2268     } end_qualList_elements;
2269
2270   qualList_clear (q);
2271 }
2272         
2273 bool
2274 uentry_isOnly (uentry ue)
2275 {
2276   return (!uentry_isUndefined (ue) 
2277           && uentry_isVariable (ue) 
2278           && alkind_isOnly (sRef_getOrigAliasKind (ue->sref)));
2279 }
2280
2281 static void
2282 uentry_setAliasKind (/*@notnull@*/ uentry ue, alkind ak)
2283 {
2284   sRef_setAliasKind (ue->sref, ak, uentry_whereDeclared (ue));
2285   sRef_setOrigAliasKind (ue->sref, ak);
2286 }
2287
2288 static void
2289 uentry_setNullState (/*@notnull@*/ uentry ue, nstate ns)
2290 {
2291   if (uentry_isVariable (ue))
2292     {
2293       ue->info->var->nullstate = ns;
2294     }
2295
2296   sRef_setNullState (ue->sref, ns, uentry_whereDeclared (ue));
2297 }
2298
2299 bool
2300 uentry_isUnique (uentry ue)
2301 {
2302   return (!uentry_isUndefined (ue) 
2303           && uentry_isVariable (ue) 
2304           && alkind_isUnique (sRef_getOrigAliasKind (ue->sref)));
2305 }
2306
2307 bool
2308 uentry_isFileStatic (uentry ue)
2309 {
2310   return (uentry_isStatic (ue) 
2311           && (!uentry_isVariable (ue)
2312               || sRef_isFileStatic (uentry_getSref (ue))));
2313 }
2314
2315 bool
2316 uentry_isExported (uentry ue)
2317 {
2318   if (uentry_isValid (ue))
2319     {
2320       if (uentry_isVariable (ue))
2321         {
2322           return (sRef_isRealGlobal (uentry_getSref (ue)));
2323         }
2324       else
2325         {
2326           return !uentry_isStatic (ue);
2327         }
2328     }
2329
2330   return FALSE;
2331 }
2332
2333 bool
2334 uentry_isNonLocal (uentry ue)
2335 {
2336   return (uentry_isValid (ue) && uentry_isVariable (ue)
2337           && (sRef_isGlobal (ue->sref) || uentry_isStatic (ue)));
2338 }
2339
2340 bool
2341 uentry_isGlobal (uentry ue)
2342 {
2343   return (uentry_isValid (ue) && uentry_isVariable (ue) && 
2344           sRef_isGlobal (ue->sref));
2345 }
2346
2347 bool
2348 uentry_isPrintfLike (uentry ue)
2349 {
2350   return (uentry_isFunction (ue) 
2351           && (ue->info->fcn->specialCode == SPC_PRINTFLIKE));
2352 }
2353
2354 bool
2355 uentry_isScanfLike (uentry ue)
2356 {
2357   return (uentry_isFunction (ue) 
2358           && (ue->info->fcn->specialCode == SPC_SCANFLIKE));
2359 }
2360
2361 bool
2362 uentry_isMessageLike (uentry ue)
2363 {
2364   return (uentry_isFunction (ue) 
2365           && (ue->info->fcn->specialCode == SPC_MESSAGELIKE));
2366 }
2367
2368 static void checkSpecialFunction (/*@notnull@*/ uentry ue)
2369 {
2370   uentryList args = uentry_getParams (ue);
2371
2372   if (!uentryList_isMissingParams (args))
2373     {
2374       uentry last = uentry_undefined;
2375
2376       uentryList_elements (args, current)
2377         {
2378           if (uentry_isElipsisMarker (current))
2379             {
2380               if (uentry_isUndefined (last))
2381                 {
2382                   voptgenerror 
2383                     (FLG_SYNTAX,
2384                      message ("Function %q is marked %s, but has no format "
2385                               "string argument before elipsis",
2386                               uentry_getName (ue),
2387                               specCode_unparse (ue->info->fcn->specialCode)),
2388                      uentry_whereLast (ue));
2389                   ue->info->fcn->specialCode = SPC_NONE;
2390                 }
2391               else
2392                 {
2393                   ctype rt = ctype_realType (uentry_getType (last));
2394
2395                   if (!ctype_match (rt, ctype_string))
2396                     {
2397                       bool okay = FALSE;
2398
2399                       /* wchar_t * is okay too */
2400                       if (ctype_isAP (rt))
2401                         {
2402                           ctype base = ctype_baseArrayPtr (rt);
2403                           
2404                           if (ctype_isArbitraryIntegral (base)) 
2405                             {
2406                               okay = TRUE;
2407                             }
2408                         }
2409                       
2410                       if (!okay) 
2411                         {
2412                           voptgenerror
2413                             (FLG_SYNTAX,
2414                              message ("Function %q is marked %s, but the argument "
2415                                       "before the elipsis has type %s (should be char *)",
2416                                       uentry_getName (ue),
2417                                       specCode_unparse (ue->info->fcn->specialCode),
2418                                       ctype_unparse (uentry_getType (last))),
2419                              uentry_whereLast (ue));
2420                           
2421                           ue->info->fcn->specialCode = SPC_NONE;
2422                         }
2423                     }
2424                 }
2425               return;
2426             }
2427           last = current;
2428         } end_uentryList_elements ;
2429
2430       voptgenerror 
2431         (FLG_SYNTAX,
2432          message ("Function %q is marked %s, but has no elipsis parameter",
2433                   uentry_getName (ue),
2434                   specCode_unparse (ue->info->fcn->specialCode)),
2435          uentry_whereLast (ue));
2436
2437       ue->info->fcn->specialCode = SPC_NONE;
2438     }
2439 }
2440
2441 void
2442 uentry_setPrintfLike (uentry ue)
2443 {
2444   if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue)))
2445     {
2446       uentry_makeVarFunction (ue);
2447     }
2448   
2449   llassertfatal (uentry_isFunction (ue));
2450   ue->info->fcn->specialCode = SPC_PRINTFLIKE;
2451   checkSpecialFunction (ue);
2452 }
2453
2454 void
2455 uentry_setScanfLike (uentry ue)
2456 {
2457   if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue)))
2458     {
2459       uentry_makeVarFunction (ue);
2460     }
2461   
2462   llassertfatal (uentry_isFunction (ue));
2463   ue->info->fcn->specialCode = SPC_SCANFLIKE;
2464   checkSpecialFunction (ue);
2465 }
2466
2467 void
2468 uentry_setMessageLike (uentry ue)
2469 {
2470   if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue)))
2471     {
2472       uentry_makeVarFunction (ue);
2473     }
2474   
2475   llassertfatal (uentry_isFunction (ue));
2476   ue->info->fcn->specialCode = SPC_MESSAGELIKE;
2477   checkSpecialFunction (ue);
2478 }
2479
2480 bool
2481 uentry_isSpecialFunction (uentry ue)
2482 {
2483   return (uentry_isFunction (ue) 
2484           && (ue->info->fcn->specialCode != SPC_NONE));
2485 }
2486
2487 /*@notnull@*/ uentry uentry_makeParam (idDecl t, int i)
2488 {
2489   ctype ct = idDecl_getCtype (t);
2490   ctype base = ct;
2491   sRef pref = sRef_makeParam (i, ct);
2492   uentry ue = uentry_makeVariableSrefParam (idDecl_observeId (t), ct, pref);
2493
2494   uentry_reflectQualifiers (ue, idDecl_getQuals (t));
2495   uentry_implicitParamAnnots (ue);
2496
2497   /* Parameter type [][] or [x][] is invalid */
2498
2499   while (ctype_isFixedArray (base)) {
2500     base = ctype_baseArrayPtr (base);
2501   }
2502   
2503   if (ctype_isIncompleteArray (base)) {
2504     base = ctype_baseArrayPtr (base);
2505
2506     if (ctype_isArray (base)) {
2507       if (!uentry_hasName (ue)) {
2508         (void) optgenerror (FLG_INCOMPLETETYPE, 
2509                             message ("Unnamed function parameter %d is incomplete type (inner array must have bounds): %s",
2510                                      i + 1,
2511                                      ctype_unparse (ct)),
2512                             uentry_whereLast (ue));
2513       } else {
2514         (void) optgenerror (FLG_INCOMPLETETYPE, 
2515                             message ("Function parameter %q is incomplete type (inner array must have bounds): %s",
2516                                      uentry_getName (ue),
2517                                      ctype_unparse (ct)),
2518                             uentry_whereLast (ue));
2519       }
2520     }
2521   }
2522
2523   return ue;
2524 }
2525
2526 /*@only@*/ /*@notnull@*/ uentry uentry_makeIdVariable (idDecl t)
2527 {
2528   ctype ct = idDecl_getCtype (t);
2529
2530   if (ctype_isFunction (ct))
2531     {
2532             return (uentry_makeIdFunction (t));
2533     }
2534   else
2535     {
2536       fileloc loc = setLocation ();
2537       uentry ue = uentry_makeVariable (idDecl_observeId (t), ct, loc, FALSE);
2538       
2539       uentry_reflectQualifiers (ue, idDecl_getQuals (t));
2540
2541       if (!uentry_isExtern (ue))
2542         {
2543           uentry_setDefined (ue, loc);
2544         }
2545
2546       return ue;
2547     }
2548 }
2549
2550 # ifndef NOLCL
2551 /*@notnull@*/ uentry uentry_makeVariableParam (cstring n, ctype t)
2552 {
2553   return (uentry_makeVariableParamAux (n, t, sRef_makeType (t), SS_DEFINED));
2554 }
2555 # endif
2556
2557 /*
2558 ** constants
2559 */
2560
2561 /*@only@*/ /*@notnull@*/ 
2562 uentry uentry_makeConstantAux (cstring n, ctype t, 
2563                                /*@keep@*/ fileloc f, bool priv,
2564                                /*@only@*/ multiVal m)
2565 {
2566   uentry e = uentry_alloc ();
2567
2568   e->ukind = KCONST;
2569   e->uname = cstring_copy (n);
2570   e->utype = t;
2571   e->storageclass = SCNONE;
2572
2573   e->sref  = sRef_makeConst (t);
2574
2575   e->lset = FALSE;
2576   e->used = FALSE;
2577   
2578   e->uses = filelocList_new ();
2579   e->isPrivate = priv;
2580   e->hasNameError = FALSE;
2581
2582   e->info = (uinfo) dmalloc (sizeof (*e->info));
2583   e->info->uconst = (ucinfo) dmalloc (sizeof (*e->info->uconst));
2584   e->info->uconst->val = m;
2585   e->info->uconst->access = typeIdSet_undefined;
2586
2587   uentry_setSpecDef (e, f);
2588
2589   if (multiVal_isInt (m) && (multiVal_forceInt (m) == 0))
2590     {
2591       sRef_setDefNull (e->sref, uentry_whereDeclared (e)); 
2592     }
2593
2594   return (e);
2595 }
2596
2597 /*@notnull@*/ uentry uentry_makeConstant (cstring n, ctype t, fileloc f)
2598 {
2599   return (uentry_makeConstantAux (n, t, f, FALSE, multiVal_unknown ()));
2600 }
2601
2602 /*@notnull@*/ uentry uentry_makeIdConstant (idDecl t)
2603 {
2604   uentry ue = uentry_makeConstant (idDecl_observeId (t), 
2605                                    idDecl_getCtype (t), 
2606                                    fileloc_undefined);
2607
2608   llassert (fileloc_isUndefined (ue->whereDeclared));
2609   ue->whereDeclared = setLocation ();
2610
2611   uentry_reflectQualifiers (ue, idDecl_getQuals (t));
2612
2613   return ue;
2614 }
2615
2616 /*
2617 ** variables
2618 */
2619
2620 void uentry_setDefState (uentry ue, sstate defstate)
2621 {
2622   if (uentry_isValid (ue))
2623     {
2624       sRef_setDefState (ue->sref, defstate, fileloc_undefined);
2625
2626       if (uentry_isVariable (ue))
2627         {
2628           ue->info->var->defstate = defstate; /* evs 2000-05-17: fixed bug, was SS_DEFINED! */
2629         }
2630     }
2631 }
2632
2633 bool uentry_isCheckedUnknown (uentry ue)
2634 {
2635   return (uentry_isVar (ue) 
2636           && (ue->info->var->checked == CH_UNKNOWN));
2637 }
2638
2639 bool uentry_isCheckMod (uentry ue)
2640 {
2641   return (uentry_isVar (ue) 
2642           && (ue->info->var->checked == CH_CHECKMOD));
2643 }
2644
2645 bool uentry_isUnchecked (uentry ue)
2646 {
2647   return (uentry_isVar (ue) 
2648           && (ue->info->var->checked == CH_UNCHECKED));
2649 }
2650
2651 bool uentry_isChecked (uentry ue)
2652 {
2653   return (uentry_isVar (ue) 
2654           && (ue->info->var->checked == CH_CHECKED));
2655 }
2656
2657 bool uentry_isCheckedModify (uentry ue)
2658 {
2659   return (uentry_isVar (ue) 
2660           && (ue->info->var->checked == CH_CHECKED
2661               || ue->info->var->checked == CH_CHECKMOD
2662               || ue->info->var->checked == CH_CHECKEDSTRICT));
2663 }
2664
2665 bool uentry_isCheckedStrict (uentry ue)
2666 {
2667   return (uentry_isVar (ue) 
2668           && (ue->info->var->checked == CH_CHECKEDSTRICT));
2669 }
2670
2671 void uentry_setUnchecked (uentry ue)
2672 {
2673   llassert (uentry_isVar (ue));
2674
2675   ue->info->var->checked = CH_UNCHECKED;
2676 }
2677
2678 void uentry_setChecked (uentry ue)
2679 {
2680   llassert (uentry_isVar (ue));
2681
2682   ue->info->var->checked = CH_CHECKED;
2683 }
2684
2685 void uentry_setCheckMod (uentry ue)
2686 {
2687   llassert (uentry_isVar (ue));
2688
2689   ue->info->var->checked = CH_CHECKMOD;
2690 }
2691
2692 void uentry_setCheckedStrict (uentry ue)
2693 {
2694   llassert (uentry_isVar (ue));
2695   
2696   ue->info->var->checked = CH_CHECKEDSTRICT;
2697 }
2698
2699 static /*@only@*/ /*@notnull@*/ 
2700   uentry uentry_makeVariableAux (cstring n, ctype t, 
2701                                  fileloc f,
2702                                  /*@exposed@*/ sRef s,
2703                                  bool priv, vkind kind)
2704 {
2705   uentry e = uentry_alloc ();
2706   ctype rt = t;
2707
2708   DPRINTF (("Make variable: %s %s %s", n, ctype_unparse (t), sRef_unparse (s)));
2709
2710   e->ukind = KVAR;
2711   e->uname = cstring_copy (n);
2712   e->utype = t;
2713
2714   e->storageclass = SCNONE;
2715
2716   e->sref  = s;
2717
2718   e->used = FALSE;
2719   e->lset = FALSE;
2720
2721   e->uses = filelocList_new ();
2722   e->isPrivate = priv;
2723   e->hasNameError = FALSE;
2724
2725   e->info = (uinfo) dmalloc (sizeof (*e->info));
2726   e->info->var = (uvinfo) dmalloc (sizeof (*e->info->var));
2727   e->info->var->kind = kind;
2728
2729   e->info->var->checked = CH_UNKNOWN;
2730
2731   uentry_setSpecDef (e, f);
2732
2733   if (ctype_isFunction (rt))
2734     {
2735       rt = ctype_returnValue (rt);
2736     }
2737
2738   if (ctype_isUA (rt))
2739     {
2740       sRef_setStateFromType (e->sref, rt);
2741     }
2742
2743   e->info->var->defstate = sRef_getDefState (e->sref);  
2744   e->info->var->nullstate = sRef_getNullState (e->sref);
2745
2746 /* start modifications */
2747 /* This function sets the uentry for a pointer or array variable declaration,
2748    it allocates memory and sets the fields. We check if the type of the variable
2749    is a pointer or array and allocate a `bbufinfo' struct accordingly */
2750
2751   if( ctype_isArray (t) || ctype_isPointer(t)) {
2752      e->info->var->bufinfo = dmalloc( sizeof(*e->info->var->bufinfo) );
2753      e->info->var->bufinfo->bufstate = BB_NOTNULLTERMINATED;
2754      s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
2755   } else {
2756      e->info->var->bufinfo = NULL;
2757   }/* end else */
2758 /* end modification */
2759
2760   return (e);
2761 }
2762
2763 bool
2764 uentry_isYield (uentry ue)
2765 {
2766   return (uentry_isVariable (ue) 
2767           && (ue->info->var->kind == VKYIELDPARAM
2768               || ue->info->var->kind == VKREFYIELDPARAM));
2769 }
2770
2771 static bool
2772 uentry_isRefsField (uentry ue)
2773 {
2774   return (uentry_isVariable (ue) && sRef_isRefsField (ue->sref));
2775 }
2776
2777 /*@only@*/ /*@notnull@*/ 
2778 uentry uentry_makeVariable (cstring n, ctype t, fileloc f, bool isPriv)
2779 {
2780   return (uentry_makeVariableAux (n, t, f, sRef_makeType (t), isPriv, 
2781                                   fileloc_isSpec (f) ? VKSPEC : VKNORMAL));
2782 }
2783
2784 /*
2785 ** functions
2786 */
2787
2788 void uentry_makeVarFunction (uentry ue)
2789 {
2790   alkind ak;
2791   exkind ek;
2792   uvinfo oldInfo;
2793   fileloc loc;
2794
2795   llassert (uentry_isValid (ue));
2796   llassert (!sRef_modInFunction ());
2797
2798   ak = sRef_getOrigAliasKind (ue->sref);
2799   ek = sRef_getOrigExKind (ue->sref);
2800
2801   oldInfo = ue->info->var;
2802
2803   llassert (ctype_isUnknown (ue->utype) || ctype_isFunction (ue->utype));
2804
2805   /*
2806   ** expanded macro is marked used (until I write a pre-processor)
2807   */
2808
2809   ue->used |= (oldInfo->kind == VKEXPMACRO);
2810
2811   ue->ukind = KFCN;
2812   ue->info->fcn = (ufinfo) dmalloc (sizeof (*ue->info->fcn));
2813   ue->info->fcn->exitCode = XK_UNKNOWN;
2814   ue->info->fcn->nullPred = QU_UNKNOWN;
2815   ue->info->fcn->specialCode = SPC_NONE;
2816   ue->info->fcn->access = typeIdSet_undefined;
2817   ue->info->fcn->hasGlobs = FALSE;
2818   ue->info->fcn->globs = globSet_undefined;
2819   ue->info->fcn->hasMods = FALSE;
2820   ue->info->fcn->mods = sRefSet_undefined;
2821   ue->info->fcn->specclauses = NULL;
2822   ue->info->fcn->defparams = uentryList_undefined;
2823
2824   if (ctype_isFunction (ue->utype))
2825     {
2826       ue->sref = sRef_makeType (ctype_returnValue (ue->utype)); 
2827     }
2828   else
2829     {
2830       ue->sref = sRef_makeType (ctype_unknown); 
2831     }
2832
2833   if (sRef_isRefCounted (ue->sref))
2834     {
2835       ak = AK_NEWREF;
2836     }
2837   else
2838     {
2839       if (alkind_isUnknown (ak))
2840         {
2841           if (exkind_isKnown (ek))
2842             {
2843               ak = AK_IMPDEPENDENT;
2844             }
2845           else 
2846             {
2847               if (context_getFlag (FLG_RETIMPONLY))
2848                 {
2849                   if (ctype_isFunction (ue->utype)
2850                       && ctype_isVisiblySharable 
2851                       (ctype_realType (ctype_returnValue (ue->utype))))
2852                     {
2853                       if (uentryList_hasReturned (uentry_getParams (ue)))
2854                         {
2855                           ;
2856                         }
2857                       else
2858                         {
2859                           ak = AK_IMPONLY;
2860                                                 }
2861                     }
2862                 }
2863             }
2864         }
2865     }
2866
2867   loc = ue->whereDeclared;
2868
2869   sRef_setAliasKind (ue->sref, ak, loc);
2870   sRef_setNullState (ue->sref, oldInfo->nullstate, loc);
2871   sRef_setDefState (ue->sref, oldInfo->defstate, loc);
2872   sRef_setExKind (ue->sref, ek, loc);
2873
2874   if (oldInfo->kind == VKEXPMACRO)
2875     {
2876       fileloc_free (loc);
2877       ue->whereDeclared = fileloc_undefined;
2878     }
2879   else
2880     {
2881       fileloc_free (ue->whereDefined);
2882       ue->whereDefined = fileloc_undefined;
2883     }
2884
2885   uvinfo_free (oldInfo);
2886 }
2887
2888 void
2889 uentry_setGlobals (uentry ue, /*@owned@*/ globSet globs)
2890 {
2891   llassert (uentry_isValid (ue));
2892
2893   if (uentry_isIter (ue))
2894     {
2895       llassert (globSet_isUndefined (ue->info->iter->globs));
2896       ue->info->iter->globs = globs;
2897     }
2898   else
2899     {
2900       if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue)))
2901         {
2902           uentry_makeVarFunction (ue);
2903         }
2904       
2905       llassert (uentry_isFunction (ue));
2906       llassert (!ue->info->fcn->hasGlobs 
2907                 && globSet_isUndefined (ue->info->fcn->globs));
2908       
2909       ue->info->fcn->hasGlobs = TRUE;
2910       /*@-mustfree@*/ ue->info->fcn->globs = globs;
2911       /*@=mustfree@*/
2912     }
2913
2914   if (globSet_hasStatic (globs))
2915     {
2916       context_recordFileGlobals (globs);
2917     }
2918
2919   if (context_getFlag (FLG_GLOBALSIMPMODIFIESNOTHING))
2920     {
2921       ue->info->fcn->hasMods = TRUE;
2922     }
2923 }
2924
2925 void uentry_addAccessType (uentry ue, typeId tid)
2926 {
2927   if (uentry_isFunction (ue))
2928     {
2929       ue->info->fcn->access = typeIdSet_insert (ue->info->fcn->access, tid);
2930     }
2931   else if (uentry_isEitherConstant (ue))
2932     {
2933       ue->info->uconst->access = typeIdSet_insert (ue->info->uconst->access, tid);
2934     }
2935   else if (uentry_isIter (ue))
2936     {
2937       ue->info->iter->access = typeIdSet_insert (ue->info->iter->access, tid);
2938     }
2939   else if (uentry_isEndIter (ue))
2940     {
2941       ue->info->enditer->access = typeIdSet_insert (ue->info->enditer->access, tid);
2942     }
2943   else
2944     {
2945       llbug (message ("no access for: %q", uentry_unparse (ue)));
2946     }
2947 }
2948
2949 /*@only@*/ /*@notnull@*/ uentry 
2950   uentry_makeFunction (cstring n, ctype t, 
2951                        typeId access, 
2952                        /*@only@*/ globSet globs, /*@only@*/ sRefSet mods, 
2953                        fileloc f)
2954 {
2955   return (uentry_makeFunctionAux (n, t, 
2956                                   ((typeId_isInvalid (access)) ? typeIdSet_emptySet () 
2957                                    : typeIdSet_single (access)),
2958                                   globs, mods, f,
2959                                   FALSE, FALSE));
2960 }
2961
2962 # ifndef NOLCL
2963 /*@notnull@*/ uentry 
2964   uentry_makePrivFunction2 (cstring n, ctype t, 
2965                             typeIdSet access, 
2966                             globSet globs, sRefSet mods, 
2967                             fileloc f)
2968 {
2969   return (uentry_makeFunctionAux (n, t, access, globs, mods, f, TRUE, FALSE));
2970 }
2971
2972
2973 /*@notnull@*/ uentry 
2974   uentry_makeSpecFunction (cstring n, ctype t, 
2975                            typeIdSet access,
2976                            /*@only@*/ globSet globs, 
2977                            /*@only@*/ sRefSet mods, 
2978                            fileloc f)
2979 {
2980   uentry ue = uentry_makeFunctionAux (n, t, access, 
2981                                       globs, mods, f,
2982                                       FALSE, FALSE);
2983
2984   uentry_setHasGlobs (ue);
2985   uentry_setHasMods (ue);
2986
2987   reflectImplicitFunctionQualifiers (ue, TRUE);
2988   return (ue);
2989 }
2990 # endif
2991
2992 uentry uentry_makeExpandedMacro (cstring s, fileloc f)
2993 {
2994   uentry ue = uentry_makeVariableAux (s, ctype_unknown, fileloc_undefined, 
2995                                       sRef_undefined, FALSE, VKEXPMACRO);
2996
2997   uentry_setDefined (ue, f);
2998   return ue;
2999 }
3000
3001 /*@notnull@*/ /*@notnull@*/ uentry 
3002   uentry_makeForwardFunction (cstring n, typeId access, fileloc f)
3003 {
3004   uentry ue = uentry_makeFunctionAux (n, ctype_unknown, 
3005                                       typeIdSet_singleOpt (access),
3006                                       globSet_undefined, sRefSet_undefined, 
3007                                       fileloc_undefined,
3008                                       FALSE, TRUE);
3009
3010   ue->whereDeclared = fileloc_update (ue->whereDeclared, f);
3011   return ue;
3012 }
3013
3014 bool uentry_isForward (uentry e)
3015 {
3016   if (uentry_isValid (e))
3017     {
3018       ctype ct = uentry_getType (e);
3019
3020       return (ctype_isUnknown (ct)
3021               || (ctype_isFunction (ct)
3022                   && ctype_isUnknown (ctype_returnValue (ct))));
3023     }
3024
3025   return FALSE;
3026 }
3027
3028 # ifndef NOLCL
3029 /*@notnull@*/ uentry 
3030 uentry_makeTypeListFunction (cstring n, typeIdSet access, fileloc f)
3031 {
3032   return (uentry_makeFunctionAux (n, ctype_unknown, access,
3033                                   globSet_new (),
3034                                   sRefSet_new (), f,
3035                                   FALSE, TRUE));
3036 }
3037
3038 /*@notnull@*/ uentry 
3039 uentry_makeUnspecFunction (cstring n, ctype t, 
3040                            typeIdSet access, 
3041                            fileloc f)
3042 {
3043   uentry ue = uentry_makeFunctionAux (n, t, access, globSet_new (),
3044                                       sRefSet_new (), f, FALSE, TRUE);
3045
3046   reflectImplicitFunctionQualifiers (ue, TRUE);
3047   return ue;
3048 }
3049 # endif
3050
3051 /*
3052 ** datatypes
3053 */
3054
3055 /* is exported for use by usymtab_interface */
3056
3057 /*@notnull@*/ uentry 
3058   uentry_makeDatatypeAux (cstring n, ctype t, ynm mut, ynm abs, 
3059                           fileloc f, bool priv)
3060 {
3061   uentry e = uentry_alloc ();
3062
3063   DPRINTF (("Make datatype: %s / %s",
3064             n, ctype_unparse (t)));
3065
3066   /* e->shallowCopy = FALSE; */
3067   e->ukind = KDATATYPE;
3068   e->uname = cstring_copy (n);
3069   e->utype = t;
3070   e->storageclass = SCNONE;
3071   e->sref  = sRef_makeUnknown ();
3072
3073   if (ctype_isUA (t))
3074     {
3075       sRef_setStateFromType (e->sref, t);
3076     }
3077
3078   uentry_setSpecDef (e, f);
3079
3080   e->uses = filelocList_new ();
3081   e->isPrivate = priv;
3082   e->hasNameError = FALSE;
3083
3084   e->used = FALSE;
3085   e->lset = FALSE;
3086
3087   e->info = (uinfo) dmalloc (sizeof (*e->info));
3088   e->info->datatype = (udinfo) dmalloc (sizeof (*e->info->datatype));
3089   e->info->datatype->abs = abs;
3090   e->info->datatype->mut = mut;
3091   e->info->datatype->type = ctype_undefined;
3092
3093   if (uentry_isDeclared (e))
3094     {
3095       uentry_setDefined (e, f);
3096     }
3097
3098   if (ynm_isOn (abs) && !(uentry_isCodeDefined (e)))
3099     {
3100       sRef_setNullState (e->sref, NS_ABSNULL, uentry_whereDeclared (e));
3101     }
3102
3103   return (e);
3104 }
3105
3106 /*@notnull@*/ uentry
3107   uentry_makeDatatype (cstring n, ctype t, ynm mut, ynm abs, 
3108                        fileloc f)
3109 {
3110   return (uentry_makeDatatypeAux (n, t, mut, abs, f, FALSE));
3111 }
3112
3113 /*@notnull@*/ uentry uentry_makeBoolDatatype (ynm abs)
3114 {
3115   uentry ret = uentry_makeDatatypeAux (context_getBoolName (),
3116                                        ctype_bool, NO, abs, 
3117                                        fileloc_getBuiltin (),
3118                                        FALSE);
3119   
3120   ret->info->datatype->type = ctype_bool;
3121   return ret;
3122 }
3123
3124 /*
3125 ** iters
3126 */
3127
3128 static /*@only@*/ /*@notnull@*/ uentry 
3129   uentry_makeIterAux (cstring n, typeIdSet access, ctype ct, 
3130                       /*@only@*/ fileloc f)
3131 {
3132   uentry e = uentry_alloc ();
3133
3134   e->ukind = KITER;
3135   e->uname = cstring_copy (n);
3136   e->utype = ct;
3137   e->sref  = sRef_makeUnknown ();
3138   e->storageclass = SCNONE;
3139   e->used = FALSE;
3140   e->lset = FALSE;
3141
3142   uentry_setSpecDef (e, f);
3143
3144   e->uses = filelocList_new ();
3145   e->isPrivate = FALSE;
3146   e->hasNameError = FALSE;
3147
3148   e->info = (uinfo) dmalloc (sizeof (*e->info));
3149   e->info->iter = (uiinfo) dmalloc (sizeof (*e->info->iter));
3150   e->info->iter->access = access;
3151   e->info->iter->mods = sRefSet_undefined;
3152   e->info->iter->globs = globSet_undefined;
3153
3154   uentry_checkIterArgs (e);
3155   return (e);
3156 }
3157
3158 /*@notnull@*/ uentry uentry_makeIter (cstring n, ctype ct, fileloc f)
3159 {
3160   return (uentry_makeIterAux (n, context_fileAccessTypes (), ct, f));
3161 }
3162
3163 static /*@notnull@*/ uentry
3164 uentry_makeEndIterAux (cstring n, typeIdSet access, /*@only@*/ fileloc f)
3165 {
3166   uentry e = uentry_alloc ();
3167
3168   /* e->shallowCopy = FALSE; */
3169   e->ukind = KENDITER;
3170   e->storageclass = SCNONE;
3171   e->uname = message ("end_%s", n);
3172   e->utype = ctype_unknown;
3173   e->sref  = sRef_makeUnknown ();
3174
3175   uentry_setSpecDef (e, f);
3176
3177   e->used = FALSE;
3178   e->lset = FALSE;
3179
3180   e->uses = filelocList_new ();
3181   e->isPrivate = FALSE;
3182   e->hasNameError = FALSE;
3183
3184   e->info = (uinfo) dmalloc (sizeof (*e->info));
3185   e->info->enditer = (ueinfo) dmalloc (sizeof (*e->info->enditer));
3186
3187   e->info->enditer->access = access;
3188
3189   return (e);
3190 }
3191
3192 /*@notnull@*/ /*@only@*/ uentry uentry_makeEndIter (cstring n, fileloc f)
3193 {
3194   return (uentry_makeEndIterAux (n, context_fileAccessTypes (), f));
3195 }
3196
3197 /*
3198 ** tags
3199 */
3200
3201 static /*@only@*/ /*@notnull@*/ uentry 
3202   uentry_makeTagAux (cstring n, ctype t, 
3203                      /*@only@*/ fileloc fl, 
3204                      bool priv, ekind kind)
3205 {
3206   uentry e = uentry_alloc ();
3207   
3208   if (kind != KSTRUCTTAG && kind != KUNIONTAG && kind != KENUMTAG)
3209     {
3210       llbuglit ("uentry_makeTagAux: not a tag type");
3211     }
3212   
3213   e->ukind = kind;
3214   /* e->shallowCopy = FALSE; */
3215   e->uname = cstring_copy (n);
3216
3217   e->utype = t;
3218   e->sref  = sRef_makeUnknown ();
3219   e->storageclass = SCNONE;
3220
3221   uentry_setSpecDef (e, fl);
3222   
3223   e->used = FALSE;
3224   e->lset = FALSE;
3225
3226   e->uses = filelocList_new ();
3227   e->isPrivate = priv;
3228   e->hasNameError = FALSE;
3229
3230   e->info = (uinfo) dmalloc (sizeof (*e->info));
3231   e->info->datatype = (udinfo) dmalloc (sizeof (*e->info->datatype));
3232   e->info->datatype->abs = NO;
3233   e->info->datatype->mut = (kind == KENUMTAG) ? NO : MAYBE;
3234   e->info->datatype->type = t;
3235
3236   if (uentry_isDeclared (e))
3237     {
3238       uentry_setDefined (e, fl);
3239     }
3240
3241   DPRINTF (("Make tag: %s / %s [%d]", uentry_unparseFull (e),
3242             ctype_unparse (t), t));
3243   return (e);  
3244 }
3245
3246 uentry uentry_makeStructTagLoc (cstring n, ctype t)
3247 {
3248   cstring sname = makeStruct (n);
3249   uentry ret = uentry_makeTagAux (sname, t, setLocation (), FALSE, KSTRUCTTAG);
3250
3251   cstring_free (sname);
3252   return (ret);
3253 }
3254
3255 /*@only@*/ uentry
3256 uentry_makeStructTag (cstring n, ctype t, fileloc loc)
3257 {
3258   cstring sname = makeStruct (n);
3259   uentry ret = uentry_makeTagAux (sname, t, loc, FALSE, KSTRUCTTAG);
3260
3261   cstring_free (sname);
3262   return ret;
3263 }
3264
3265 /*@only@*/ uentry
3266 uentry_makeUnionTag (cstring n, ctype t, fileloc loc)
3267 {
3268   cstring uname = makeUnion (n);
3269   uentry ret = uentry_makeTagAux (uname, t, loc, FALSE, KUNIONTAG);
3270
3271   cstring_free (uname);
3272   return (ret);
3273 }
3274
3275 # ifndef NOLCL
3276 uentry
3277 uentry_makeEnumTag (cstring n, ctype t, fileloc loc)
3278 {
3279   cstring ename = makeEnum (n);
3280   uentry ret = uentry_makeTagAux (ename, t, loc, FALSE, KENUMTAG);
3281
3282   cstring_free (ename);
3283   return ret;
3284 }
3285 # endif
3286
3287 uentry
3288 uentry_makeUnionTagLoc (cstring n, ctype t)
3289 {
3290   cstring uname = makeUnion (n);
3291   uentry ret = uentry_makeTagAux (uname, t, setLocation (), FALSE, KUNIONTAG);
3292
3293   cstring_free (uname);
3294   return ret;
3295 }
3296
3297 uentry
3298 uentry_makeEnumTagLoc (cstring n, ctype t)
3299 {
3300   cstring ename = makeEnum (n);
3301   uentry ret = uentry_makeTagAux (ename, t, setLocation (), FALSE, KENUMTAG);
3302
3303   cstring_free (ename);
3304   return ret;
3305 }
3306
3307 bool 
3308 uentry_isStructTag (uentry ue) 
3309 {
3310   return (uentry_isValid (ue) && ue->ukind == KSTRUCTTAG);
3311 }
3312
3313 bool 
3314 uentry_isUnionTag (uentry ue) 
3315 {
3316   return (uentry_isValid (ue) && ue->ukind == KUNIONTAG);
3317 }
3318
3319 bool 
3320 uentry_isEnumTag (uentry ue) 
3321 {
3322   return (uentry_isValid (ue) && ue->ukind == KENUMTAG);
3323 }
3324
3325 bool
3326 uentry_isAnyTag (uentry ue)
3327 {
3328   return (uentry_isStructTag (ue) 
3329           || uentry_isUnionTag (ue)
3330           || uentry_isEnumTag (ue));
3331 }
3332
3333 static /*@unchecked@*/ /*@only@*/ uentry emarker = NULL;
3334
3335 extern void uentry_destroyMod (void)
3336    /*@globals killed emarker@*/ /*@modifies emarker@*/
3337 {
3338   static bool wasDestroyed = FALSE;
3339
3340   llassert (!wasDestroyed);
3341
3342   if (emarker != NULL)
3343     {
3344       uentry_reallyFree (emarker);
3345     }
3346
3347   wasDestroyed = TRUE;
3348 }
3349
3350 uentry
3351 uentry_makeElipsisMarker (void)
3352 {
3353   if (emarker == NULL)
3354     {
3355       emarker = uentry_alloc ();
3356
3357       emarker->ukind = KELIPSMARKER;
3358       emarker->uname = cstring_makeLiteral ("...");
3359       emarker->utype = ctype_elipsMarker;
3360       emarker->sref  = sRef_undefined;
3361       emarker->storageclass = SCNONE;
3362       emarker->used = FALSE;
3363       emarker->lset = FALSE;
3364       emarker->info = NULL;
3365
3366       uentry_setSpecDef (emarker, fileloc_undefined);
3367       emarker->uses = filelocList_new ();
3368       emarker->isPrivate = FALSE;
3369       emarker->hasNameError = FALSE;
3370     }
3371
3372   /*@ignore@*/ return (emarker); /*@end@*/
3373
3374
3375 /*
3376 ** comparisons
3377 */
3378
3379 bool
3380 uentry_equiv (uentry p1, uentry p2)
3381 {
3382   if (uentry_compare (p1, p2) != 0)
3383     {
3384       return FALSE;
3385     }
3386   else
3387     {
3388       return TRUE;
3389     }
3390 }
3391
3392 int
3393 uentry_xcomparealpha (uentry *p1, uentry *p2)
3394 {
3395   int res;
3396
3397   if ((res = uentry_compare (*p1, *p2)) == 0) {
3398     if ((*p1 != NULL) && (*p2 != NULL)) {
3399       res = cstring_compare ((*p1)->uname,
3400                              (*p2)->uname);
3401     }
3402   }
3403
3404   return res;
3405 }
3406
3407 int
3408 uentry_xcompareuses (uentry *p1, uentry *p2)
3409 {
3410   uentry u1 = *p1;
3411   uentry u2 = *p2;
3412
3413   if (uentry_isValid (u1))
3414     {
3415       if (uentry_isValid (u2))
3416         {
3417           return (-1 * int_compare (filelocList_size (u1->uses), 
3418                                     filelocList_size (u2->uses)));
3419         }
3420       else
3421         {
3422           return 1;
3423         }
3424     }
3425   else
3426     {
3427       if (uentry_isValid (u2))
3428         {
3429           return -1;
3430         }
3431       else
3432         {
3433           return 0;
3434         }
3435     }
3436 }
3437
3438 int 
3439 uentry_compareStrict (uentry v1, uentry v2)
3440 {
3441   COMPARERETURN (uentry_compare (v1, v2));
3442
3443   if (v1 != v2 && uentry_isValid (v1) && uentry_isValid (v2))
3444     {
3445       COMPARERETURN (fileloc_compare (v1->whereDeclared, v2->whereDeclared));
3446       COMPARERETURN (fileloc_compare (v1->whereDefined, v2->whereDefined));
3447       COMPARERETURN (fileloc_compare (v1->whereSpecified, v2->whereSpecified));
3448     }
3449
3450   return 0;
3451 }
3452
3453 int
3454 uentry_compare (uentry u1, uentry u2)
3455 {
3456   if (u1 == u2) return 0;
3457   
3458   if (uentry_isInvalid (u1)) return -1;
3459   if (uentry_isInvalid (u2)) return 1;
3460
3461   INTCOMPARERETURN (u1->ukind, u2->ukind);
3462   COMPARERETURN (ctype_compare (u1->utype, u2->utype));
3463   COMPARERETURN (bool_compare (uentry_isPriv (u1), uentry_isPriv (u2)));
3464
3465   COMPARERETURN (sRef_compare (u1->sref, u2->sref));
3466
3467   switch (u1->ukind)
3468     {
3469     case KINVALID:
3470     case KELIPSMARKER:
3471       /* bug detected by lclint:  
3472       ** uentry.c:753,14: Return value type bool does not match declared type int: TRUE 
3473       */
3474       return 0;
3475     case KENUMCONST:
3476     case KCONST:
3477       return (multiVal_compare (u1->info->uconst->val,
3478                                 u2->info->uconst->val));
3479     case KSTRUCTTAG: 
3480     case KUNIONTAG: 
3481     case KENUMTAG: 
3482       return (ctype_compare (u1->info->datatype->type, u2->info->datatype->type));
3483     case KITER:
3484       COMPARERETURN (typeIdSet_compare (uentry_accessType (u1), 
3485                                          uentry_accessType (u2)));
3486       return (uentryList_compareParams (uentry_getParams (u1), 
3487                                         uentry_getParams (u2)));
3488     case KENDITER:
3489       return (typeIdSet_compare (uentry_accessType (u1), 
3490                                   uentry_accessType (u2)));
3491     case KFCN:
3492       COMPARERETURN (typeIdSet_compare (uentry_accessType (u1), 
3493                                          uentry_accessType (u2)));
3494       COMPARERETURN (globSet_compare (uentry_getGlobs (u1), 
3495                                       uentry_getGlobs (u2)));
3496       COMPARERETURN (uentryList_compareParams (uentry_getParams (u1), 
3497                                                uentry_getParams (u2)));
3498       COMPARERETURN (generic_compare (u1->info->fcn->specialCode,
3499                                        u2->info->fcn->specialCode));
3500       COMPARERETURN (generic_compare (u1->info->fcn->nullPred,
3501                                        u2->info->fcn->nullPred));
3502
3503       return (sRefSet_compare (uentry_getMods (u1), uentry_getMods (u2)));
3504     case KVAR:
3505       COMPARERETURN (generic_compare (u1->info->var->kind, u2->info->var->kind));
3506       COMPARERETURN (generic_compare (sRef_getOrigAliasKind (u1->sref),
3507                                       sRef_getOrigAliasKind (u2->sref)));
3508       COMPARERETURN (generic_compare (sRef_getOrigExKind (u1->sref),
3509                                       sRef_getOrigExKind (u2->sref)));
3510       COMPARERETURN (generic_compare (u1->info->var->checked,
3511                                       u2->info->var->checked));
3512       COMPARERETURN (generic_compare (u1->info->var->defstate, 
3513                                       u2->info->var->defstate));
3514       return        (generic_compare (u1->info->var->nullstate, 
3515                                       u2->info->var->nullstate));
3516     case KDATATYPE:
3517       COMPARERETURN (ctype_compare (u1->info->datatype->type,
3518                                     u2->info->datatype->type));
3519       COMPARERETURN (ynm_compare (u1->info->datatype->mut,
3520                                   u2->info->datatype->mut));
3521       return (ynm_compare (u1->info->datatype->abs, u2->info->datatype->abs));
3522     }
3523   
3524   BADEXIT;
3525 }
3526
3527 /*
3528 ** library format:
3529 **
3530 ** all entries are: <type>[@<info>]*#<name>
3531 **
3532 ** info depends on kind:
3533 */
3534
3535 static void
3536 advanceField (char **s)
3537 {
3538   checkChar (s, '@');
3539 }
3540
3541 static void
3542 advanceName (char **s)
3543 {
3544   checkChar (s, '#');
3545 }
3546
3547 static vkind
3548 vkind_fromInt (int i)
3549 {
3550   if /*@+enumint@*/ (i < VKFIRST || i > VKLAST) /*@=enumint@*/
3551     {
3552       llbuglit ("vkind_fromInt: out of range");
3553     }
3554
3555   return (vkind)i;
3556 }
3557
3558 static uentry  
3559   uentry_makeConstantBase (/*@only@*/ cstring name, ctype ct, 
3560                            typeIdSet access, nstate nullstate,
3561                            /*@keep@*/ fileloc loc, /*@only@*/ multiVal m)
3562 {
3563   uentry e = uentry_alloc ();
3564   
3565   e->ukind = KCONST;
3566   e->uname = name;
3567   e->utype = ct;
3568   e->sref  = sRef_makeConst (ct);
3569
3570   sRef_setNullState (e->sref, nullstate, loc);
3571   e->storageclass = SCNONE;
3572
3573   if (fileloc_isSpec (loc))
3574     {
3575       e->whereSpecified = loc;
3576       e->whereDeclared = fileloc_undefined;
3577     }
3578   else
3579     {
3580       e->whereSpecified = fileloc_undefined;
3581       e->whereDeclared = loc;
3582     }
3583
3584   e->whereDefined = fileloc_undefined;
3585   e->uses = filelocList_new ();
3586   e->isPrivate = FALSE;
3587   e->hasNameError = FALSE;
3588
3589   e->used = FALSE;
3590   e->lset = FALSE;
3591
3592   e->info = (uinfo) dmalloc (sizeof (*e->info));
3593   e->info->uconst = (ucinfo) dmalloc (sizeof (*e->info->uconst));
3594   e->info->uconst->val = m;
3595   e->info->uconst->access = access;
3596
3597   sRef_storeState (e->sref);
3598
3599   return (e);
3600 }
3601
3602 static /*@only@*/ uentry  
3603   uentry_makeVariableBase (/*@only@*/ cstring name, ctype ct, vkind kind, 
3604                            sstate defstate, nstate isnull, alkind aliased,
3605                            exkind exp, chkind checked, 
3606                            /*@only@*/ fileloc loc)
3607 {
3608   uentry e = uentry_alloc ();
3609
3610   e->ukind = KVAR;
3611   e->uname = name;
3612   e->utype = ct;
3613   e->storageclass = SCNONE;
3614
3615   e->sref  = sRef_makeType (ct);
3616   sRef_setNullState (e->sref, isnull, loc);
3617
3618   e->whereDefined = fileloc_undefined;
3619
3620   if (fileloc_isSpec (loc))
3621     {
3622       e->whereSpecified = loc;
3623       e->whereDeclared = fileloc_undefined;
3624     }
3625   else
3626     {
3627       e->whereSpecified = fileloc_undefined;
3628       e->whereDeclared = loc;
3629     }
3630
3631   e->isPrivate = FALSE;
3632   e->hasNameError = FALSE;
3633
3634   e->used = FALSE;
3635   e->lset = FALSE;
3636
3637   e->uses = filelocList_new ();
3638
3639   e->info = (uinfo) dmalloc (sizeof (*e->info));
3640   e->info->var = (uvinfo) dmalloc (sizeof (*e->info->var));
3641   e->info->var->kind = kind;
3642   e->info->var->checked = checked;
3643   e->info->var->defstate = defstate;
3644
3645   sRef_setDefState (e->sref, defstate, loc);
3646
3647   e->info->var->nullstate = sRef_getNullState (e->sref);
3648
3649   sRef_setExKind (e->sref, exp, loc);
3650   sRef_setAliasKind (e->sref, aliased, loc);
3651
3652   sRef_storeState (e->sref);
3653   return (e);
3654 }
3655
3656 static /*@only@*/ uentry  
3657 uentry_makeDatatypeBase (/*@only@*/ cstring name, ctype ct, ynm abs, 
3658                          ynm mut, ctype rtype, alkind ak, exkind exp, 
3659                          sstate defstate, nstate isnull,
3660                          /*@only@*/ fileloc loc)
3661 {
3662   uentry e = uentry_alloc ();
3663
3664   e->ukind = KDATATYPE;
3665   /* e->shallowCopy = FALSE; */
3666   e->uname = name;
3667   e->utype = ct;
3668   e->storageclass = SCNONE;
3669   e->sref  = sRef_makeUnknown ();
3670
3671   /*
3672   ** This is only setting null state.  (I think?)
3673   */
3674
3675   if (ctype_isUA (ct))
3676     {
3677       uentry te = usymtab_getTypeEntrySafe (ctype_typeId (ct));
3678
3679       if (uentry_isValid (te))
3680         {
3681           sRef_setStateFromUentry (e->sref, te);
3682         }
3683       else
3684         {
3685           /* problem for recursive type definitions */
3686         }
3687     }
3688   
3689   sRef_setAliasKind (e->sref, ak, loc);
3690   sRef_setExKind (e->sref, exp, loc);
3691
3692   sRef_setDefState (e->sref, defstate, loc);
3693
3694   if (ynm_isOn (abs) && ctype_isUnknown (ct) && isnull == NS_UNKNOWN)
3695     {
3696       isnull = NS_ABSNULL;
3697     }
3698
3699   sRef_mergeNullState (e->sref, isnull);
3700
3701   e->whereDefined = fileloc_copy (loc); /*< bogus!  (but necessary for lexer) >*/
3702
3703   if (fileloc_isSpec (loc))
3704     {
3705       e->whereSpecified = loc;
3706       e->whereDeclared = fileloc_undefined;
3707     }
3708   else
3709     {
3710       e->whereSpecified = fileloc_undefined;
3711       e->whereDeclared = loc;
3712     }
3713   
3714   e->isPrivate = FALSE;
3715   e->hasNameError = FALSE;
3716
3717   e->used = FALSE;
3718   e->lset = FALSE;
3719   e->uses = filelocList_new ();
3720
3721   e->info = (uinfo) dmalloc (sizeof (*e->info));
3722   e->info->datatype = (udinfo) dmalloc (sizeof (*e->info->datatype));
3723   e->info->datatype->abs = abs;
3724   e->info->datatype->mut = mut;
3725   e->info->datatype->type = rtype;
3726   
3727   sRef_storeState (e->sref);
3728
3729   return (e);
3730 }
3731
3732 # ifndef NOLCL
3733 static void uentry_setHasGlobs (uentry ue)
3734 {
3735   llassert (uentry_isFunction (ue));
3736
3737   ue->info->fcn->hasGlobs = TRUE;
3738 }
3739
3740 static void uentry_setHasMods (uentry ue)
3741 {
3742   llassert (uentry_isFunction (ue));
3743
3744   ue->info->fcn->hasMods = TRUE;
3745 }
3746 # endif
3747
3748 bool uentry_hasGlobs (uentry ue)
3749 {
3750   if (uentry_isFunction (ue))
3751     {
3752       return (ue->info->fcn->hasGlobs);
3753     }
3754
3755   return FALSE;
3756 }
3757
3758 bool uentry_hasSpecialClauses (uentry ue)
3759 {
3760   return (uentry_isFunction (ue) && specialClauses_isDefined (ue->info->fcn->specclauses));
3761 }
3762
3763 specialClauses uentry_getSpecialClauses (uentry ue)
3764 {
3765   llassert (uentry_isFunction (ue));
3766   return ue->info->fcn->specclauses;
3767 }
3768
3769 bool uentry_hasMods (uentry ue)
3770 {
3771   if (uentry_isFunction (ue))
3772     {
3773       return (ue->info->fcn->hasMods);
3774     }
3775
3776   return FALSE;
3777 }
3778
3779 static uentry  
3780   uentry_makeFunctionBase (/*@only@*/ cstring name, ctype ct, 
3781                            typeIdSet access, 
3782                            bool hasGlobs, /*@only@*/ globSet globs, 
3783                            bool hasMods, /*@only@*/ sRefSet mods, 
3784                            alkind ak, exkind exp, 
3785                            sstate defstate, nstate isnull,
3786                            exitkind exitCode,
3787                            specCode sCode,
3788                            qual nullPred,
3789                            /*@only@*/ specialClauses specclauses,
3790                            /*@only@*/ fileloc loc)
3791 {
3792   uentry e = uentry_alloc ();
3793   ctype ret;
3794
3795   /* e->shallowCopy = FALSE; */
3796   e->ukind = KFCN;
3797   e->uname = name;
3798   e->utype = ct;
3799   e->storageclass = SCNONE;
3800
3801   if (ctype_isFunction (ct))
3802     {
3803       ret = ctype_returnValue (ct);
3804     }
3805   else
3806     {
3807       if (ctype_isKnown (ct))
3808         {
3809           llbug (message ("not function: %s", ctype_unparse (ct)));
3810         }
3811
3812       ret = ctype_unknown;
3813     }
3814
3815   e->sref  = sRef_makeType (ret);
3816
3817   if (ctype_isUA (ret))
3818     {
3819       sRef_setStateFromType (e->sref, ret);
3820     }
3821
3822   sRef_setDefined (e->sref, loc);
3823   sRef_setNullState (e->sref, isnull, loc);
3824
3825   sRef_setAliasKind (e->sref, ak, loc);
3826   sRef_setExKind (e->sref, exp, loc);
3827   sRef_setDefState (e->sref, defstate, loc);
3828
3829   e->whereSpecified = loc;
3830   e->whereDefined = fileloc_undefined;
3831
3832   e->isPrivate = FALSE;
3833   e->hasNameError = FALSE;
3834
3835   e->used = FALSE;
3836   e->lset = FALSE;
3837   e->uses = filelocList_new ();  
3838
3839   e->info = (uinfo) dmalloc (sizeof (*e->info));
3840   e->info->fcn = (ufinfo) dmalloc (sizeof (*e->info->fcn));
3841   
3842   e->info->fcn->exitCode = exitCode;
3843   e->info->fcn->specialCode = sCode;
3844   e->info->fcn->nullPred = nullPred;
3845   e->info->fcn->access = access;
3846
3847   e->info->fcn->specclauses = specclauses;
3848   e->info->fcn->hasGlobs = hasGlobs;
3849   e->info->fcn->globs = globs;
3850
3851   e->info->fcn->hasMods = hasMods;
3852   e->info->fcn->mods = mods;
3853
3854   e->info->fcn->defparams = uentryList_undefined; 
3855   e->whereDeclared = fileloc_undefined;
3856
3857   sRef_storeState (e->sref);
3858
3859   return (e);
3860 }
3861
3862 static /*@only@*/ uentry  
3863   uentry_makeTagBase (/*@only@*/ cstring name, ekind tagkind, 
3864                       ctype ct, ctype rtype, /*@only@*/ fileloc loc)
3865 {
3866   uentry e = uentry_alloc ();
3867   
3868   if (tagkind != KSTRUCTTAG && tagkind != KUNIONTAG && tagkind != KENUMTAG)
3869     {
3870       llbuglit ("uentry_makeTagBase: not a tag type");
3871     }
3872
3873   /* e->shallowCopy = FALSE; */
3874   e->ukind = tagkind;
3875   e->uname = name;
3876   e->utype = ct;
3877   e->sref  = sRef_makeUnknown ();
3878   e->storageclass = SCNONE;
3879
3880   if (fileloc_isSpec (loc))
3881     {
3882       e->whereSpecified = loc;
3883       e->whereDeclared = fileloc_undefined;
3884     }
3885   else
3886     {
3887       e->whereDeclared = loc;
3888       e->whereSpecified = fileloc_undefined;
3889     }
3890
3891   e->whereDefined = fileloc_undefined;
3892
3893   e->isPrivate = FALSE;
3894   e->hasNameError = FALSE;
3895
3896   e->used = FALSE;
3897   e->lset = FALSE;
3898   e->uses = filelocList_new ();
3899
3900   e->info = (uinfo) dmalloc (sizeof (*e->info));
3901   e->info->datatype = (udinfo) dmalloc (sizeof (*e->info->datatype));
3902   e->info->datatype->abs  = NO;
3903   e->info->datatype->mut  = MAYBE;
3904   e->info->datatype->type = rtype;
3905
3906   sRef_storeState (e->sref);
3907
3908   return (e);  
3909 }
3910
3911 static uentry  
3912   uentry_makeIterBase (/*@only@*/ cstring name, typeIdSet access, 
3913                        ctype ct, /*@only@*/ fileloc loc)
3914 {
3915   uentry e = uentry_alloc ();
3916   
3917   /* e->shallowCopy = FALSE; */
3918   e->ukind = KITER;
3919   e->uname = name;
3920   e->utype = ct;
3921   e->sref  = sRef_makeUnknown ();
3922   e->storageclass = SCNONE;
3923
3924   if (fileloc_isSpec (loc))
3925     {
3926       e->whereSpecified = loc;
3927       e->whereDeclared = fileloc_undefined;
3928     }
3929   else
3930     {
3931       e->whereDeclared = loc;
3932       e->whereSpecified = fileloc_undefined;
3933     }
3934
3935   e->whereDefined = fileloc_undefined;
3936   
3937   e->isPrivate = FALSE;
3938   e->hasNameError = FALSE;
3939
3940   e->used = FALSE;
3941   e->lset = FALSE;
3942   e->uses = filelocList_new ();
3943
3944   e->info = (uinfo) dmalloc (sizeof (*e->info));
3945   e->info->iter = (uiinfo) dmalloc (sizeof (*e->info->iter));
3946   e->info->iter->access = access;
3947   e->info->iter->mods = sRefSet_undefined;
3948   e->info->iter->globs = globSet_undefined;
3949   
3950   sRef_storeState (e->sref);
3951   return (e);
3952 }
3953
3954 static uentry  
3955   uentry_makeEndIterBase (/*@only@*/ cstring name, typeIdSet access, 
3956                           /*@only@*/ fileloc loc)
3957 {
3958   uentry e = uentry_alloc ();
3959
3960   /* e->shallowCopy = FALSE; */
3961   e->ukind = KENDITER;
3962   e->storageclass = SCNONE;
3963   e->uname = name;
3964   e->utype = ctype_unknown;
3965   e->sref  = sRef_makeUnknown ();
3966   
3967   if (fileloc_isSpec (loc))
3968     {
3969       e->whereSpecified = loc;
3970       e->whereDeclared = fileloc_undefined;
3971     }
3972   else
3973     {
3974       e->whereDeclared = loc;
3975       e->whereSpecified = fileloc_undefined;
3976     }
3977
3978   e->whereDefined = fileloc_undefined;
3979
3980   e->isPrivate = FALSE;
3981   e->hasNameError = FALSE;
3982
3983   e->used = FALSE;
3984   e->lset = FALSE;
3985   e->uses = filelocList_new ();
3986
3987   e->info = (uinfo) dmalloc (sizeof (*e->info));
3988   e->info->enditer = (ueinfo) dmalloc (sizeof (*e->info->enditer));
3989   e->info->enditer->access = access;
3990   sRef_storeState (e->sref);
3991
3992   return (e);
3993 }
3994
3995 void uentry_markFree (/*@unused@*/ /*@owned@*/ uentry u)
3996 {
3997   /* should save u */
3998 /*@-mustfree@*/
3999 }
4000 /*@=mustfree@*/
4001
4002 /*@only@*/ uentry
4003 uentry_undump (ekind kind, fileloc loc, char **s)
4004 {
4005   uentry ue;
4006   
4007   if (**s == '!')
4008     {
4009       checkChar (s, '!');
4010       checkChar (s, '.');
4011       ue = uentry_makeElipsisMarker ();
4012     }
4013   else
4014     {
4015       ctype ct = ctype_undump (s);
4016       cstring name;
4017
4018       switch (kind)
4019         {
4020         case KVAR:
4021           {
4022             vkind  tkind;
4023             sstate defstate;
4024             nstate isnull;
4025             alkind aliased;
4026             exkind exp;
4027             chkind checked;
4028             
4029             checkChar (s, '|');
4030
4031             if (optCheckChar (s, '@'))
4032               {
4033                 tkind = vkind_fromInt (getInt (s));
4034                 checkChar (s, '|');
4035               }
4036             else
4037               {
4038                 tkind = VKPARAM;
4039               }
4040
4041             if (optCheckChar (s, '$'))
4042               {
4043                 defstate = SS_UNKNOWN;
4044                 isnull = NS_UNKNOWN;
4045                 aliased = AK_IMPTEMP;
4046                 exp = XO_UNKNOWN;
4047                 checked = CH_UNKNOWN;
4048               }         
4049             else if (optCheckChar (s, '&'))
4050               {
4051                 defstate = SS_DEFINED;
4052                 isnull = NS_UNKNOWN;
4053                 aliased = AK_IMPTEMP;
4054                 exp = XO_UNKNOWN;
4055                 checked = CH_UNKNOWN;
4056               }         
4057             else if (optCheckChar (s, '^'))
4058               {
4059                 defstate = SS_UNKNOWN;
4060                 isnull = NS_UNKNOWN;
4061                 aliased = AK_IMPTEMP;
4062                 exp = XO_UNKNOWN;
4063                 checked = CH_UNKNOWN;
4064               }         
4065             else
4066               {
4067                 defstate = sstate_fromInt (getInt (s));      
4068                 advanceField (s); isnull = nstate_fromInt (getInt (s));      
4069                 advanceField (s); aliased = alkind_fromInt (getInt (s));      
4070
4071                 if (optCheckChar (s, '&'))
4072                   {
4073                     exp = XO_UNKNOWN;
4074                     checked = CH_UNKNOWN;
4075                   }
4076                 else
4077                   {
4078                     advanceField (s); exp = exkind_fromInt (getInt (s));      
4079                     advanceField (s); checked = (chkind) (getInt (s));      
4080                   }
4081               }
4082
4083             advanceName (s);
4084             name = getStringWord (s);
4085             
4086             ue = uentry_makeVariableBase (name, ct, tkind, defstate, 
4087                                           isnull, aliased, exp, 
4088                                           checked, fileloc_copy (loc));
4089           }
4090           break;
4091         case KDATATYPE: 
4092           {
4093             ynm abs;
4094             ynm mut;
4095             ctype rtype;
4096             sstate defstate;
4097             nstate isnull;
4098             alkind aliased;
4099             exkind exp;
4100
4101             advanceField (s); abs = ynm_fromCodeChar (loadChar (s));
4102             advanceField (s); mut = ynm_fromCodeChar (loadChar (s));
4103             advanceField (s); defstate = sstate_fromInt (getInt (s));      
4104             advanceField (s); isnull = nstate_fromInt (getInt (s));      
4105             advanceField (s); aliased = alkind_fromInt (getInt (s));      
4106             advanceField (s); exp = exkind_fromInt (getInt (s));      
4107             advanceField (s); rtype = ctype_undump (s);
4108             advanceName (s); 
4109             name = getStringWord (s);
4110
4111             ue = uentry_makeDatatypeBase (name, ct, abs, mut, rtype, 
4112                                           aliased, exp, defstate, isnull, 
4113                                           fileloc_copy (loc));
4114           }
4115           break;
4116         case KFCN:
4117           {
4118             alkind     ak;
4119             exkind     exp;
4120             sstate     defstate;
4121             nstate     isnull;
4122             exitkind   exitCode;
4123             specCode   specc;
4124             qual       nullPred;
4125             typeIdSet access;
4126             bool       hasGlobs;
4127             globSet    globs;
4128             bool       hasMods;
4129             sRefSet    mods;
4130             specialClauses specclauses;
4131
4132             if (optCheckChar (s, '$'))
4133               {
4134                 defstate = SS_DEFINED;
4135                 isnull = NS_UNKNOWN;
4136                 exitCode = XK_UNKNOWN;
4137                 specc = SPC_NONE;
4138                 nullPred = QU_UNKNOWN;
4139               }
4140             else
4141               {
4142                 advanceField (s); defstate = sstate_fromInt (getInt (s)); 
4143                 advanceField (s); isnull = nstate_fromInt (getInt (s)); 
4144                 advanceField (s); exitCode = exitkind_fromInt (getInt (s)); 
4145                 advanceField (s); specc = specCode_fromInt (getInt (s)); 
4146                 advanceField (s); nullPred = qual_fromInt (getInt (s)); 
4147               }
4148
4149             if (optCheckChar (s, '$'))
4150               {
4151                 hasGlobs = FALSE;
4152                 globs = globSet_undefined;
4153                 hasMods = FALSE;
4154                 mods = sRefSet_undefined;
4155               }
4156             else if (optCheckChar (s, '^'))
4157               {
4158                 hasGlobs = TRUE;
4159                 globs = globSet_undefined;
4160                 hasMods = TRUE;
4161                 mods = sRefSet_undefined;
4162               }
4163             else
4164               {
4165                 advanceField (s); hasGlobs = bool_fromInt (getInt (s));
4166                 advanceField (s); globs  = globSet_undump (s);
4167                 advanceField (s); hasMods = bool_fromInt (getInt (s));
4168                 advanceField (s); mods   = sRefSet_undump (s);      
4169               }
4170
4171             if (optCheckChar (s, '$'))
4172               {
4173                 ak = AK_UNKNOWN;
4174                 exp = XO_UNKNOWN;
4175               }
4176             else
4177               {
4178                 advanceField (s); ak = alkind_fromInt (getInt (s));
4179                 advanceField (s); exp = exkind_fromInt (getInt (s));      
4180               }
4181
4182             advanceField (s); access = typeIdSet_undump (s);
4183
4184             if (optCheckChar (s, '@'))
4185               {
4186                 specclauses = specialClauses_undump (s);
4187               }
4188             else
4189               {
4190                 specclauses = specialClauses_undefined; 
4191               }
4192
4193             advanceName (s);  name = getStringWord (s);
4194
4195             ue = uentry_makeFunctionBase (name, ct, access, 
4196                                           hasGlobs, globs, 
4197                                           hasMods, mods, 
4198                                           ak, exp, defstate, isnull, 
4199                                           exitCode, specc, nullPred,
4200                                           specclauses,
4201                                           fileloc_copy (loc));
4202             DPRINTF (("Undump: %s", uentry_unparse (ue)));
4203           }
4204           break;
4205         case KITER:
4206           {
4207             typeIdSet access;
4208             
4209             advanceField (s); access = typeIdSet_undump (s);
4210             advanceName (s);  name = getStringWord (s);
4211             
4212             ue = uentry_makeIterBase (name, access, ct,
4213                                       fileloc_copy (loc));
4214           }
4215           break;
4216         case KENDITER:
4217           {
4218             typeIdSet access;
4219
4220             advanceField (s); access = typeIdSet_undump (s);
4221             advanceName (s);  name = getStringWord (s);
4222             
4223             ue = uentry_makeEndIterBase (name, access, fileloc_copy (loc));
4224           }
4225           break;
4226         case KENUMCONST:  
4227         case KCONST:  
4228           {
4229             typeIdSet access;
4230             multiVal val;
4231             nstate nullstate;
4232
4233             if (optCheckChar (s, '$'))
4234               {
4235                 val = multiVal_undefined;
4236                 access = typeIdSet_undefined;
4237                 nullstate = NS_UNKNOWN;
4238               }
4239             else
4240               {
4241                 advanceField (s); val = multiVal_undump (s);
4242                 advanceField (s); access = typeIdSet_undump (s);
4243                 advanceField (s); nullstate = nstate_fromInt (getInt (s));
4244               }
4245
4246             advanceName (s);  name = getStringWord (s);
4247             
4248             ue = uentry_makeConstantBase (name, ct, access,
4249                                           nullstate, fileloc_copy (loc), val);
4250             break;
4251           }
4252         case KSTRUCTTAG:
4253         case KUNIONTAG:
4254         case KENUMTAG:
4255           {
4256             ctype rtype;
4257             
4258             advanceField (s); rtype = ctype_undump (s);
4259             advanceName (s);  name = getStringWord (s);
4260             ue = uentry_makeTagBase (name, kind, ct, rtype, fileloc_copy (loc));
4261           }
4262           break;
4263         case KINVALID:
4264           llcontbuglit ("uentry_undump: invalid");
4265           ue = uentry_undefined;
4266           break;
4267         case KELIPSMARKER:
4268           llcontbuglit ("uentry_undump: elips marker");
4269           ue = uentry_undefined;
4270           break;
4271         }
4272     }
4273   
4274   return (ue);
4275 }
4276
4277 cstring
4278 uentry_dump (uentry v)
4279 {
4280   return (uentry_dumpAux (v, FALSE));
4281 }
4282
4283 cstring
4284 uentry_dumpParam (uentry v)
4285 {
4286   llassertprint (uentry_isVariable (v) || uentry_isElipsisMarker (v),
4287                  ("dump: %s", uentry_unparseFull (v)));
4288
4289   return (uentry_dumpAux (v, TRUE));
4290 }
4291
4292 static cstring
4293 uentry_dumpAux (uentry v, bool isParam)
4294 {
4295   llassert (uentry_isValid (v));
4296
4297   DPRINTF (("Dumping entry: %s", uentry_unparseFull (v)));
4298
4299   switch (v->ukind)
4300     {
4301     case KINVALID: 
4302       llcontbuglit ("uentry_dump: invalid entry"); 
4303       return cstring_undefined;
4304     case KELIPSMARKER: 
4305       return (message ("!."));
4306     case KVAR:     
4307       {
4308         cstring sdump;
4309         vkind vk  = v->info->var->kind;
4310         sstate dss = sRef_getDefState (v->sref);
4311         nstate nst = sRef_getNullState (v->sref);
4312         alkind alk = sRef_getAliasKind (v->sref);
4313         exkind exk = sRef_getExKind (v->sref);
4314         chkind chk = v->info->var->checked;
4315
4316         DPRINTF (("Dumping var"));
4317
4318         if (dss == SS_UNKNOWN
4319             && nst == NS_UNKNOWN
4320             && alk == AK_IMPTEMP
4321             && exk == XO_UNKNOWN
4322             && chk == CH_UNKNOWN)
4323           {
4324             sdump = cstring_makeLiteral ("$");
4325           }
4326         else if (dss == SS_DEFINED
4327                  && nst == NS_UNKNOWN
4328                  && alk == AK_IMPTEMP
4329                  && exk == XO_UNKNOWN
4330                  && chk == CH_UNKNOWN)
4331           {
4332             sdump = cstring_makeLiteral ("&");
4333           }
4334         else if (dss == SS_UNKNOWN
4335                  && nst == NS_UNKNOWN
4336                  && alk == AK_UNKNOWN
4337                  && exk == XO_UNKNOWN
4338                  && chk == CH_UNKNOWN)
4339           {
4340             sdump = cstring_makeLiteral ("^");
4341           }
4342         else if (exk == XO_UNKNOWN
4343                  && chk == CH_UNKNOWN)
4344           {
4345             sdump = message ("%d@%d@%d&",
4346                              (int) dss,
4347                              (int) nst,
4348                              (int) alk);
4349           }
4350         else
4351           {
4352             sdump = message ("%d@%d@%d@%d@%d",  
4353                      (int) dss,
4354                              (int) nst,
4355                              (int) alk,
4356                              (int) exk,
4357                              (int) chk);
4358           }
4359         
4360
4361         if (vk != VKPARAM)
4362           {
4363             return (message ("%q|@%d|%q#%s", 
4364                              ctype_dump (v->utype), 
4365                              (int) vk,
4366                              sdump,
4367                              isParam ? cstring_undefined : v->uname));
4368           }
4369         else
4370           {
4371             return (message ("%q|%q#%s", 
4372                              ctype_dump (v->utype), 
4373                              sdump,
4374                              isParam ? cstring_undefined : v->uname));
4375           }
4376
4377       }
4378     case KDATATYPE: 
4379       return (message ("%q@%s@%s@%d@%d@%d@%d@%q#%s", 
4380                        ctype_dump (v->utype),
4381                        ynm_unparseCode (v->info->datatype->abs),
4382                        ynm_unparseCode (v->info->datatype->mut),
4383                        (int) sRef_getDefState (v->sref),
4384                        (int) sRef_getNullState (v->sref),
4385                        (int) sRef_getAliasKind (v->sref),
4386                        (int) sRef_getExKind (v->sref),
4387                        ctype_dump (v->info->datatype->type),
4388                        v->uname));
4389     case KFCN:
4390       {
4391         cstring sdump, gdump, adump;
4392         alkind alk = sRef_getAliasKind (v->sref);
4393         exkind exk = sRef_getExKind (v->sref);
4394
4395         if (sRef_getDefState (v->sref) == SS_DEFINED
4396             && !nstate_isKnown (sRef_getNullState (v->sref))
4397             && !exitkind_isKnown (v->info->fcn->exitCode)
4398             && v->info->fcn->specialCode == SPC_NONE
4399             && v->info->fcn->nullPred == QU_UNKNOWN)
4400           {
4401             sdump = cstring_makeLiteral ("$");
4402           }
4403         else
4404           {
4405             sdump = message ("@%d@%d@%d@%d@%d",
4406                              (int) sRef_getDefState (v->sref),
4407                              (int) sRef_getNullState (v->sref),
4408                              (int) v->info->fcn->exitCode,
4409                              (int) v->info->fcn->specialCode,
4410                              (int) v->info->fcn->nullPred);
4411           }
4412
4413         if (!uentry_hasGlobs(v) && !uentry_hasMods (v))
4414           {
4415             gdump = cstring_makeLiteral ("$");
4416           }
4417         else if (uentry_hasGlobs (v) && globSet_isEmpty (uentry_getGlobs (v))
4418                  && uentry_hasMods (v) && sRefSet_isEmpty (uentry_getMods (v)))
4419           {
4420             gdump = cstring_makeLiteral ("^");
4421           }
4422         else
4423           {
4424             gdump = message ("@%s@%q@%s@%q",
4425                              bool_dump (uentry_hasGlobs (v)),
4426                              globSet_dump (uentry_getGlobs (v)),
4427                              bool_dump (uentry_hasMods (v)),
4428                              sRefSet_dump (uentry_getMods (v)));
4429           }
4430
4431         if (alk == AK_UNKNOWN && exk == XO_UNKNOWN)
4432           {
4433             adump = cstring_makeLiteral ("$");
4434           }
4435         else
4436           {
4437             adump = message ("@%d@%d", (int) alk, (int) exk);
4438           }
4439
4440         if (uentry_hasSpecialClauses (v))
4441           {
4442             return (message ("%q%q%q%q@%q@%q#%s",
4443                              ctype_dump (v->utype),
4444                              sdump,
4445                              gdump,
4446                              adump,
4447                              typeIdSet_dump (uentry_accessType (v)),
4448                              specialClauses_dump (v->info->fcn->specclauses),
4449                              v->uname));
4450           }
4451         else
4452           {
4453             return (message ("%q%q%q%q@%q#%s",
4454                              ctype_dump (v->utype),
4455                              sdump,
4456                              gdump,
4457                              adump,
4458                              typeIdSet_dump (uentry_accessType (v)),
4459                              v->uname));
4460           }
4461       }
4462     case KITER:
4463       return (message ("%q@%q#%s",
4464                        ctype_dump (v->utype),
4465                        typeIdSet_dump (v->info->iter->access),
4466                        v->uname));
4467     case KENDITER:
4468       return (message ("%q@%q#%s",
4469                        ctype_dump (v->utype),
4470                        typeIdSet_dump (uentry_accessType (v)),
4471                        v->uname));
4472     case KENUMCONST:  
4473     case KCONST:  
4474       {
4475         cstring sdump;
4476
4477         if (multiVal_isUnknown (v->info->uconst->val)
4478             && typeIdSet_isEmpty (uentry_accessType (v))
4479             && (sRef_getNullState (v->sref) == NS_UNKNOWN))
4480           {
4481             sdump = cstring_makeLiteral ("$");
4482           }
4483         else
4484           {
4485             sdump = message ("@%q@%q@%d",
4486                              multiVal_dump (v->info->uconst->val),
4487                              typeIdSet_dump (uentry_accessType (v)),
4488                              (int) sRef_getNullState (v->sref));
4489           }
4490
4491         return (message ("%q%q#%s", 
4492                          ctype_dump (v->utype), 
4493                          sdump,
4494                          v->uname));
4495       }
4496     case KSTRUCTTAG:
4497     case KUNIONTAG:
4498     case KENUMTAG:
4499       return (message ("%q@%q#%s", 
4500                        ctype_dump (v->utype), 
4501                        ctype_dump (v->info->datatype->type), v->uname));
4502     }
4503
4504   BADEXIT;
4505 }
4506
4507 /*@only@*/ cstring
4508 uentry_unparseAbbrev (uentry v)
4509 {
4510   if (!uentry_isVariable (v))
4511     {
4512       llcontbuglit ("uentry_unparseAbbrev: not variable");
4513       return uentry_unparse (v);
4514     }
4515
4516   return (message ("%s %q", ctype_unparseDeep (v->utype), uentry_getName (v)));
4517 }
4518
4519 /*@only@*/ cstring
4520 uentry_unparse (uentry v)
4521 {
4522   cstring st;
4523
4524     if (uentry_isUndefined (v)) return (cstring_makeLiteral ("<undefined>"));
4525   if (uentry_isElipsisMarker (v)) return (cstring_makeLiteral ("..."));
4526
4527   st = uentry_getName (v);
4528
4529   if (cstring_isDefined (st))
4530     {
4531       return (ctype_unparseDeclaration (v->utype, st)); 
4532     }
4533   else
4534     {
4535       cstring_free (st);
4536       return (cstring_copy (ctype_unparse (v->utype)));
4537     }
4538 }
4539
4540 /*@only@*/ cstring
4541 uentry_unparseFull (uentry v)
4542 {
4543   if (uentry_isUndefined (v))
4544     {
4545       return (cstring_makeLiteral ("<undefined>"));
4546     }
4547   else if (uentry_isDatatype (v))
4548     {
4549       return (message ("[%d] [%s] %s %q : %t [%t] %s %s // %q [s: %q; d: %q]",
4550                        (int) v,
4551                        ekind_unparse (v->ukind),
4552                        v->uname,
4553                        uentry_getName (v),
4554                        v->utype,
4555                        ctype_isDefined (v->info->datatype->type) 
4556                           ? v->info->datatype->type : ctype_unknown,
4557                        ynm_unparse (v->info->datatype->mut),
4558                        ynm_unparse (v->info->datatype->abs),
4559                        sRef_unparseState (v->sref),
4560                        fileloc_unparse (v->whereSpecified),
4561                        fileloc_unparse (v->whereDefined)));
4562     }
4563   else if (uentry_isFunction (v))
4564     {
4565       return (message ("[%w] = [%s] %q : %t / sref: %q / mods: %q / "
4566                        "globs: %q / [s: %q; decl: %q; def: %q]",
4567                        (long unsigned) v,
4568                        ekind_unparse (v->ukind),
4569                        uentry_getName (v),
4570                        v->utype,
4571                        sRef_unparseFull (v->sref),
4572                        sRefSet_unparse (v->info->fcn->mods),
4573                        globSet_unparse  (v->info->fcn->globs),
4574                        fileloc_unparse (v->whereSpecified),
4575                        fileloc_unparse (v->whereDeclared),
4576                        fileloc_unparse (v->whereDefined)));
4577     }
4578   else if (uentry_isIter (v))
4579     {
4580       return (message ("[%s] %q: %t / %q [s: %q; d: %q]",
4581                        ekind_unparse (v->ukind),
4582                        uentry_getName (v),
4583                        v->utype,
4584                        sRef_unparseFull (v->sref),
4585                        fileloc_unparse (v->whereSpecified),
4586                        fileloc_unparse (v->whereDefined)));
4587     }
4588   else if (uentry_isVariable (v))
4589     {
4590       return 
4591         (message ("[check: %s] / [%w] = [%s] %s : %t %q [s: %q; def: %q; dec: %q] "
4592                   "kind <%d> isout <%d> used <%d>",
4593                   checkedName (v->info->var->checked),
4594                   (long unsigned) v,
4595                   ekind_unparse (v->ukind),
4596                   v->uname,
4597                   v->utype,
4598                   sRef_unparseDeep (v->sref),
4599                   fileloc_unparse (v->whereSpecified),
4600                   fileloc_unparse (v->whereDefined),
4601                   fileloc_unparse (v->whereDeclared),
4602                   (int) v->info->var->kind,
4603                   (int) v->info->var->defstate,
4604                   (int) v->used));
4605     }
4606   else
4607     {
4608       return (message ("[%s] %s : %t %q at [s: %q; d: %q]",
4609                        ekind_unparse (v->ukind),
4610                        v->uname,
4611                        v->utype,
4612                        sRef_unparseFull (v->sref),
4613                        fileloc_unparse (v->whereSpecified),
4614                        fileloc_unparse (v->whereDefined)));
4615       
4616     }
4617 }
4618
4619 bool uentry_hasAccessType (uentry e)
4620 {
4621   if (uentry_isValid (e))
4622     {
4623       switch (e->ukind)
4624         {
4625         case KITER:
4626           return (!typeIdSet_isEmpty (e->info->iter->access));
4627         case KENDITER:
4628           return (!typeIdSet_isEmpty (e->info->enditer->access));
4629         case KFCN:
4630           return (!typeIdSet_isEmpty (e->info->fcn->access));
4631         case KENUMCONST:
4632         case KCONST:
4633           return (!typeIdSet_isEmpty (e->info->uconst->access));
4634         default:
4635           return FALSE;
4636         }
4637     }
4638
4639   return FALSE;
4640 }
4641   
4642 typeIdSet uentry_accessType (uentry e)
4643 {
4644   if (uentry_isValid (e))
4645     {
4646       switch (e->ukind)
4647         {
4648         case KITER:
4649           return (e->info->iter->access);
4650         case KENDITER:
4651           return (e->info->enditer->access);
4652         case KFCN:
4653           return (e->info->fcn->access);
4654         case KENUMCONST:
4655         case KCONST:
4656           return (e->info->uconst->access);
4657         default:
4658           break;
4659         }
4660     }
4661
4662   return typeIdSet_undefined;
4663 }
4664
4665 bool
4666 uentry_isVariable (uentry e)
4667 {
4668   return (uentry_isVar (e));
4669 }
4670
4671 bool
4672 uentry_isSpecified (uentry e)
4673 {
4674   return (uentry_isValid (e) && !fileloc_isUndefined (e->whereSpecified));
4675 }
4676
4677 static bool
4678 uentry_isReallySpecified (uentry e)
4679 {
4680   return (uentry_isValid (e) 
4681           && fileloc_isRealSpec (e->whereSpecified));
4682 }
4683
4684 bool
4685 uentry_isVar (uentry e)
4686 {
4687   return (!uentry_isUndefined (e) && e->ukind == KVAR);
4688 }
4689
4690 bool 
4691 uentry_isFakeTag (uentry e)
4692 {
4693   return (uentry_isValid (e) && strchr (cstring_toCharsSafe (e->uname), '!') != 0);
4694 }
4695
4696 bool
4697 uentry_isDatatype (uentry e)
4698 {
4699   return (!uentry_isUndefined (e) &&
4700           (e->ukind == KDATATYPE || e->ukind == KSTRUCTTAG ||
4701            e->ukind == KUNIONTAG || e->ukind == KENUMTAG));
4702 }
4703
4704 void
4705 uentry_setAbstract (uentry e)
4706 {
4707   typeId oldid;
4708
4709   llassert (uentry_isDatatype (e) 
4710             && (ynm_isMaybe (e->info->datatype->abs)));
4711
4712   oldid = ctype_typeId (e->info->datatype->type);
4713   e->info->datatype->abs = YES;
4714   e->info->datatype->type = ctype_createAbstract (oldid);
4715 }
4716
4717 void
4718 uentry_setConcrete (uentry e)
4719 {
4720   llassert (uentry_isDatatype (e) 
4721             && (ynm_isMaybe (e->info->datatype->abs)));
4722
4723   e->info->datatype->abs = NO;
4724 }
4725
4726 bool
4727 uentry_isAbstractDatatype (uentry e)
4728 {
4729   return (uentry_isDatatype (e) 
4730           && (ynm_isOn (e->info->datatype->abs)));
4731 }
4732
4733 bool
4734 uentry_isMaybeAbstract (uentry e)
4735 {
4736   return (uentry_isDatatype (e) 
4737           && (ynm_isMaybe (e->info->datatype->abs)));
4738 }
4739
4740 bool
4741 uentry_isMutableDatatype (uentry e)
4742 {
4743   bool res = uentry_isDatatype (e) 
4744     && (ynm_toBoolRelaxed (e->info->datatype->mut));
4745   
4746   return res;
4747 }
4748
4749 bool
4750 uentry_isRefCountedDatatype (uentry e)
4751 {
4752   return (uentry_isDatatype (e) && (sRef_isRefCounted (uentry_getSref (e))));
4753 }
4754
4755 bool
4756 uentry_isParam (uentry u)
4757 {
4758   return (uentry_isVariable (u) && (u->info->var->kind == VKPARAM
4759                                     || u->info->var->kind == VKYIELDPARAM));
4760 }
4761
4762 bool
4763 uentry_isExpandedMacro (uentry u)
4764 {
4765   return (uentry_isVariable (u) && (u->info->var->kind == VKEXPMACRO));
4766 }
4767
4768 bool
4769 uentry_isSefParam (uentry u)
4770 {
4771   return (uentry_isVariable (u) 
4772           && (u->info->var->kind == VKSEFPARAM
4773               || u->info->var->kind == VKREFSEFPARAM
4774               || u->info->var->kind == VKSEFRETPARAM
4775               || u->info->var->kind == VKREFSEFRETPARAM));
4776 }
4777
4778 bool
4779 uentry_isRefParam (uentry u)
4780 {
4781   return (uentry_isVariable (u) 
4782           && (u->info->var->kind == VKREFPARAM
4783               || u->info->var->kind == VKREFYIELDPARAM
4784               || u->info->var->kind == VKREFSEFPARAM
4785               || u->info->var->kind == VKREFSEFRETPARAM));
4786 }
4787
4788 bool
4789 uentry_isAnyParam (uentry u)
4790 {
4791   return (uentry_isVariable (u) 
4792           && ((u->info->var->kind == VKPARAM)
4793               || (u->info->var->kind == VKSEFPARAM)
4794               || (u->info->var->kind == VKYIELDPARAM)
4795               || (u->info->var->kind == VKRETPARAM)
4796               || (u->info->var->kind == VKSEFRETPARAM)));
4797 }
4798
4799 sstate 
4800 uentry_getDefState (uentry u)
4801 {
4802   if (uentry_isValid (u))
4803     {
4804       return (sRef_getDefState (u->sref));
4805     }
4806   else
4807     {
4808       return (SS_UNKNOWN);
4809     }
4810 }
4811
4812 bool
4813 uentry_isOut (uentry u)
4814 {
4815   return ((uentry_isVariable (u) && (u->info->var->defstate == SS_ALLOCATED))
4816           || (uentry_isDatatype (u) && (sRef_isAllocated (u->sref))));
4817 }
4818
4819 bool
4820 uentry_isPartial (uentry u)
4821 {
4822   return ((uentry_isVariable (u) && (u->info->var->defstate == SS_PARTIAL))
4823           || (uentry_isDatatype (u) && (sRef_isAllocated (u->sref))));
4824 }
4825
4826 bool
4827 uentry_isStateSpecial (uentry u)
4828 {
4829   return ((uentry_isVariable (u) 
4830            && (u->info->var->defstate == SS_SPECIAL))
4831           || (uentry_isValid (u) && sRef_isStateSpecial (u->sref)));
4832 }
4833
4834 exitkind uentry_getExitCode (uentry ue) 
4835 {
4836   if (uentry_isFunction (ue))
4837     {
4838       return ue->info->fcn->exitCode;
4839     }
4840   else
4841     {
4842       return XK_UNKNOWN;
4843     }
4844 }
4845
4846 qual
4847 uentry_nullPred (uentry u)
4848 {
4849   llassert (uentry_isRealFunction (u));
4850
4851   if (uentry_isFunction (u))
4852     {
4853       return (u->info->fcn->nullPred);
4854     }
4855   else
4856     {
4857       return QU_UNKNOWN;
4858     }
4859 }
4860
4861 bool
4862 uentry_possiblyNull (uentry u)
4863 {
4864   return ((uentry_isVariable (u) && (nstate_possiblyNull (u->info->var->nullstate)))
4865           || (uentry_isDatatype (u) && (sRef_possiblyNull (u->sref))));
4866 }
4867
4868 alkind 
4869 uentry_getAliasKind (uentry u)
4870 {
4871   if (uentry_isValid (u))
4872     {
4873       return (sRef_getAliasKind (uentry_getSref (u)));
4874     }
4875   else
4876     {
4877       return AK_UNKNOWN;
4878     }
4879 }
4880
4881 exkind 
4882 uentry_getExpKind (uentry u)
4883 {
4884   if (uentry_isValid (u))
4885     {
4886       return (sRef_getExKind (uentry_getSref (u)));
4887     }
4888   else
4889     {
4890       return XO_UNKNOWN;
4891     }
4892 }
4893
4894 bool
4895 uentry_isIter (uentry e)
4896 {
4897   return (!uentry_isUndefined (e) && e->ukind == KITER);
4898 }
4899
4900 bool
4901 uentry_isEndIter (uentry e)
4902 {
4903   return (!uentry_isUndefined (e) && e->ukind == KENDITER);
4904 }
4905
4906 bool
4907 uentry_isRealFunction (uentry e)
4908 {
4909   return (uentry_isFunction (e) ||
4910           (uentry_isVariable (e) && ctype_isFunction (uentry_getType (e))));
4911 }
4912
4913 bool
4914 uentry_hasName (uentry e)
4915 {
4916   if (uentry_isValid (e))
4917     {
4918       cstring s = e->uname;
4919       
4920       return (!(cstring_isEmpty (s) || cstring_equalLit (s, "...")));
4921     }
4922   else
4923     {
4924       return FALSE;
4925     }
4926 }
4927
4928 bool uentry_hasRealName (uentry e)
4929 {
4930   return (uentry_isValid (e) && cstring_isNonEmpty (e->uname));
4931 }
4932
4933
4934 /*@observer@*/ globSet
4935 uentry_getGlobs (uentry l)
4936 {
4937   if (uentry_isInvalid (l)) 
4938     {
4939       return globSet_undefined;
4940     }
4941
4942   if (l->ukind != KFCN)
4943     {
4944       if (l->ukind != KITER && l->ukind != KENDITER)
4945         {
4946           if (l->ukind == KVAR)
4947             {
4948               llbug (message ("Bad call to uentry_getGlobs (var): %q (%s)", 
4949                               uentry_unparse (l), 
4950                               ekind_unparse (l->ukind)));
4951             }
4952           else
4953             {
4954               llbug (message ("Bad call to uentry_getGlobs: %q (%s)", 
4955                               uentry_unparse (l), 
4956                               ekind_unparse (l->ukind)));
4957             }
4958         }
4959       return globSet_undefined;
4960     }
4961
4962   return l->info->fcn->globs;
4963 }
4964
4965 /*@observer@*/ sRefSet
4966 uentry_getMods (uentry l)
4967 {
4968   llassert (uentry_isValid (l));
4969
4970   if (l->ukind != KFCN && l->ukind != KITER && l->ukind != KENDITER)
4971     {
4972       llcontbug (message ("Bad call to uentry_getMods: %q", uentry_unparse (l)));
4973       return sRefSet_undefined; 
4974     }
4975
4976   return l->info->fcn->mods;
4977 }
4978
4979 ekind
4980 uentry_getKind (uentry e)
4981 {
4982   llassert (uentry_isValid (e));
4983
4984   return (e->ukind);
4985 }
4986
4987 /*@observer@*/ multiVal uentry_getConstantValue (uentry e)
4988 {
4989   llassert (uentry_isEitherConstant (e));
4990
4991   return (e->info->uconst->val);
4992 }
4993
4994 /*@observer@*/ uentryList
4995 uentry_getParams (uentry l)
4996 {
4997   if (uentry_isInvalid (l)) return uentryList_undefined;
4998
4999   switch (l->ukind)
5000     {
5001     case KFCN:  
5002     case KITER:
5003       {
5004         ctype ct = l->utype;
5005
5006         if (ctype_isFunction (ct))
5007           {
5008             return (ctype_argsFunction (ct));
5009           }
5010         else
5011           {
5012             return uentryList_undefined;
5013           }
5014       }
5015     case KVAR:  
5016       {
5017         ctype ct = l->utype;
5018
5019         llassert (ctype_isFunction (ct));
5020         return (ctype_argsFunction (ct));
5021       }
5022     BADDEFAULT;
5023     }
5024   BADEXIT;
5025 }
5026
5027 /*@observer@*/ cstring
5028 uentry_rawName (uentry e)
5029 {
5030   if (uentry_isValid (e))
5031     {
5032       return (e->uname);
5033     }
5034   else
5035     {
5036       return cstring_undefined;
5037     }
5038 }
5039
5040 static cstring
5041 uentry_getOptName (uentry e)
5042 {
5043   cstring s = uentry_getName (e);
5044
5045   if (cstring_isDefined (s))
5046     {
5047       s = cstring_appendChar (s, ' ');
5048     }
5049   
5050   return s;
5051 }
5052
5053 /*@only@*/ cstring
5054 uentry_getName (uentry e)
5055 {
5056   cstring ret = cstring_undefined;
5057
5058   if (uentry_isValid (e))
5059     {
5060       
5061       if (uentry_isAnyTag (e))
5062         {
5063           ret = fixTagName (e->uname); 
5064         }
5065       else if (uentry_isAnyParam (e))
5066         {
5067           ret = cstring_copy (fixParamName (e->uname));
5068         }
5069       else
5070         {
5071           ret = cstring_copy (e->uname);
5072         }
5073     }
5074
5075   return ret;
5076 }
5077
5078 cstring uentry_getRealName (uentry e)
5079 {
5080   if (uentry_isValid (e))
5081     {
5082       if (uentry_isAnyTag (e))
5083         {
5084           return (cstring_undefined);
5085         }
5086       else
5087         {
5088           return (e->uname);
5089         }
5090     }
5091   return cstring_undefined;
5092 }
5093
5094 ctype uentry_getType (uentry e)
5095 {
5096   if (uentry_isValid (e))
5097     {
5098       return e->utype;
5099     }
5100   else
5101     {
5102       return ctype_unknown;
5103     }
5104 }
5105
5106 fileloc uentry_whereLast (uentry e)
5107 {
5108   fileloc loc;
5109
5110   if (uentry_isInvalid (e)) 
5111     {
5112       return fileloc_undefined;
5113     }
5114   
5115   loc = e->whereDefined;
5116
5117   if (fileloc_isValid (loc) && !fileloc_isExternal (loc))
5118     {
5119       return loc;
5120     }
5121
5122   loc = uentry_whereDeclared (e);
5123
5124   if (fileloc_isValid (loc) && !fileloc_isExternal (loc))
5125     {
5126       return loc;
5127     }
5128
5129   loc = uentry_whereSpecified (e);
5130   return loc;
5131 }
5132
5133 fileloc uentry_whereEither (uentry e)
5134 {
5135   if (uentry_isInvalid (e)) return fileloc_undefined;
5136
5137   if (fileloc_isDefined (e->whereDefined) 
5138       && !fileloc_isExternal (e->whereDefined))
5139     {
5140       return e->whereDefined;
5141     }
5142   else if (fileloc_isDefined (e->whereDeclared))
5143     {
5144       return e->whereDeclared;
5145     }
5146   else
5147     {
5148       return e->whereSpecified;
5149     }
5150 }
5151
5152 fileloc uentry_whereSpecified (uentry e)
5153 {
5154   if (uentry_isInvalid (e)) return fileloc_undefined;
5155
5156   return (e->whereSpecified);
5157 }
5158
5159 fileloc uentry_whereDefined (uentry e)
5160 {
5161   if (uentry_isInvalid (e)) return fileloc_undefined;
5162
5163   return (e->whereDefined);
5164 }
5165
5166 fileloc uentry_whereDeclared (uentry e)
5167 {
5168   if (uentry_isInvalid (e)) return fileloc_undefined;
5169
5170   return (e->whereDeclared);
5171 }
5172
5173 /*@observer@*/ fileloc
5174 uentry_whereEarliest (uentry e)
5175 {
5176   if (uentry_isInvalid (e)) return fileloc_undefined;
5177   
5178   if (fileloc_isDefined (e->whereSpecified))
5179     {
5180       return (e->whereSpecified);
5181     }
5182   else if (fileloc_isDefined (e->whereDeclared))
5183     {
5184       return (e->whereDeclared);
5185     }
5186   else
5187     {
5188       return e->whereDefined;
5189     }
5190 }
5191
5192 void
5193 uentry_setFunctionDefined (uentry e, fileloc loc)
5194 {
5195   if (uentry_isValid (e))
5196     {
5197       llassert (uentry_isFunction (e));
5198
5199       if (fileloc_isUndefined (e->whereDeclared))
5200         {
5201           e->whereDeclared = fileloc_update (e->whereDeclared, loc);
5202         }
5203       
5204       if (!fileloc_isDefined (e->whereDefined))
5205         {
5206           e->whereDefined = fileloc_update (e->whereDefined, loc);
5207         }
5208     }
5209 }
5210
5211 void
5212 uentry_setDeclDef (uentry e, fileloc f)
5213 {
5214   uentry_setDeclared (e, f);
5215   
5216   if (!uentry_isFunction (e)
5217       && !(uentry_isVariable (e) && uentry_isExtern (e)))
5218     {
5219       uentry_setDefined (e, f);
5220     }
5221 }
5222
5223 void
5224 uentry_setDeclaredForce (uentry e, fileloc f)
5225 {
5226   llassert (uentry_isValid (e));
5227   e->whereDeclared = fileloc_update (e->whereDeclared, f);
5228 }
5229
5230 void
5231 uentry_setDeclaredForceOnly (uentry e, fileloc f)
5232 {
5233   llassert (uentry_isValid (e));
5234   fileloc_free (e->whereDeclared);
5235   e->whereDeclared = f;
5236 }
5237
5238 void
5239 uentry_setDeclaredOnly (uentry e, /*@only@*/ fileloc f)
5240 {
5241   fileloc oldloc;
5242
5243   llassert (uentry_isValid (e));
5244   oldloc = e->whereDeclared;  
5245
5246   if (fileloc_isDefined (oldloc))
5247     {
5248       if (fileloc_isLib (oldloc) || fileloc_isImport (oldloc))
5249         {
5250           e->whereDeclared = f;
5251           fileloc_free (oldloc);
5252         }
5253       else
5254         {
5255           fileloc_free (f);
5256         }
5257     }
5258   else
5259     {
5260       e->whereDeclared = f;
5261       fileloc_free (oldloc);
5262     }
5263 }
5264   
5265 void
5266 uentry_setDeclared (uentry e, fileloc f)
5267 {
5268   fileloc oldloc;
5269
5270   llassert (uentry_isValid (e));
5271   oldloc = e->whereDeclared;  
5272
5273   if (fileloc_isDefined (oldloc))
5274     {
5275       if (fileloc_isLib (oldloc) || fileloc_isImport (oldloc))
5276         {
5277           e->whereDeclared = fileloc_update (e->whereDeclared, f);
5278         }
5279       else
5280         {
5281           ;
5282         }
5283     }
5284   else
5285     {
5286       e->whereDeclared = fileloc_update (e->whereDeclared, f);
5287     }
5288 }
5289
5290 void
5291 uentry_clearDefined (uentry e)
5292 {
5293   if (uentry_isValid (e))
5294     {
5295       e->whereDefined = fileloc_update (e->whereDefined, fileloc_undefined);
5296     }
5297 }
5298
5299 void
5300 uentry_setDefined (uentry e, fileloc f)
5301 {
5302   fileloc oldloc;
5303
5304   llassert (uentry_isValid (e));
5305   oldloc = e->whereDefined;
5306
5307   if (fileloc_isDefined (oldloc))
5308     {
5309       if (fileloc_isLib (oldloc) 
5310           || fileloc_isImport (oldloc)
5311           || fileloc_isBuiltin (oldloc) 
5312           || fileloc_isPreproc (oldloc))
5313         {
5314           e->whereDefined = fileloc_update (e->whereDefined, f);
5315         }
5316       else
5317         {
5318           if (fileloc_equal (oldloc, f) || context_processingMacros ())
5319             {
5320               ; /* okay */
5321             }
5322           else
5323             {
5324               if (optgenerror (FLG_REDEF,
5325                                message ("%s %q redefined", 
5326                                         ekind_capName (e->ukind),
5327                                         uentry_getName (e)),
5328                                f))
5329                 {
5330                   llgenindentmsg (message ("Previous definition of %q", 
5331                                            uentry_getName (e)),
5332                                   e->whereDefined);
5333                 }
5334             }
5335         }
5336     }
5337   else
5338     {
5339       e->whereDefined = fileloc_update (e->whereDefined, f);
5340     }
5341 }
5342
5343 bool
5344 uentry_isCodeDefined (uentry e)
5345 {
5346   return (uentry_isValid (e) && fileloc_isDefined (e->whereDefined));
5347 }
5348
5349 bool
5350 uentry_isDeclared (uentry e)
5351 {
5352   if (uentry_isValid (e))
5353     {
5354       return (fileloc_isDefined (e->whereDeclared));
5355     }
5356
5357   return FALSE;
5358 }
5359
5360 sRef uentry_getSref (uentry e)
5361 {
5362   /* not true, used for functions too (but shouldn't be? */
5363   /* llassertprint (e->ukind == KVAR, ("uentry_getSref: not variable!")); */
5364
5365   if (uentry_isInvalid (e)) return sRef_undefined;
5366   
5367   return (e->sref);
5368 }
5369
5370 sRef uentry_getOrigSref (uentry e)
5371 {
5372   if (uentry_isValid (e))
5373     {
5374       sRef sr = sRef_copy (uentry_getSref (e));
5375       
5376       sRef_resetState (sr);
5377       sRef_clearDerived (sr);
5378       
5379       if (uentry_isVariable (e))
5380         {
5381           sRef_setDefState (sr, e->info->var->defstate, fileloc_undefined);
5382           sRef_setNullState (sr, e->info->var->nullstate, fileloc_undefined);
5383         }
5384       
5385       return (sr);
5386     }
5387   else
5388     {
5389       return sRef_undefined;
5390     }
5391 }
5392
5393 /*
5394 ** requires: uentry e is not in a hashed symbol table
5395 */
5396
5397 void 
5398 uentry_setName (uentry e, /*@only@*/ cstring n)
5399 {
5400   llassert (uentry_isValid (e));
5401
5402   cstring_free (e->uname);
5403   e->uname = n;
5404 }
5405
5406 void
5407 uentry_setType (uentry e, ctype t)
5408 {
5409   if (uentry_isValid (e)) 
5410     {
5411       e->utype = t;
5412       sRef_setType (e->sref, t);
5413     }
5414 }
5415
5416 void
5417 uentry_resetParams (uentry ue, /*@only@*/ uentryList pn)
5418 {
5419   ctype rct;
5420   ctype rettype = ctype_unknown;
5421   
5422   llassert (uentry_isValid (ue));
5423
5424   rct = ctype_realType (ue->utype);
5425
5426   if (uentry_isVariable (ue) && (ctype_isFunction (rct) || ctype_isUnknown (rct)))
5427     {
5428       uentry_makeVarFunction (ue);
5429     }
5430
5431   llassert (uentry_isFunction (ue));
5432
5433   if (ctype_isFunction (rct))
5434     {
5435       rettype = ctype_returnValue (rct);
5436     }
5437
5438   ue->utype = ctype_makeNFParamsFunction (rettype, pn);      
5439 }
5440
5441 void
5442 uentry_setRefParam (uentry e)
5443 {
5444   
5445   if (!uentry_isVar (e))
5446     {
5447       llbug (message ("uentry_setParam: not variable: %q", uentry_unparse (e)));
5448     }
5449   else
5450     {
5451       if (e->info->var->kind == VKSEFPARAM)
5452         {
5453           e->info->var->kind = VKREFSEFPARAM;
5454         }
5455       else if (e->info->var->kind == VKSEFRETPARAM)
5456         {
5457           e->info->var->kind = VKREFSEFRETPARAM;
5458         }
5459       else if (e->info->var->kind == VKYIELDPARAM)
5460         {
5461           e->info->var->kind = VKREFYIELDPARAM;
5462         }
5463       else
5464         {
5465           e->info->var->kind = VKREFPARAM;
5466         }
5467     }
5468 }
5469
5470 void
5471 uentry_setParam (uentry e)
5472 {
5473   if (!uentry_isVar (e))
5474     {
5475       if (uentry_isElipsisMarker (e))
5476         {
5477
5478         }
5479       else
5480         {
5481           llbug (message ("uentry_setParam: not variable: %q", uentry_unparse (e)));
5482         }
5483     }
5484   else
5485     {
5486       cstring oldname;
5487
5488       if (e->info->var->kind == VKYIELDPARAM 
5489           || e->info->var->kind == VKSEFPARAM
5490           || e->info->var->kind == VKSEFRETPARAM)
5491         {
5492           ;
5493         }
5494       else
5495         {
5496           e->info->var->kind = VKPARAM;
5497         }
5498
5499       oldname = e->uname;
5500       e->uname = makeParam (e->uname);
5501       cstring_free (oldname);
5502     }
5503 }
5504
5505 void
5506 uentry_setSref (uentry e, sRef s)
5507 {
5508   if (uentry_isValid (e))
5509     {
5510       if (sRef_isValid (e->sref))
5511         {
5512           sRef_mergeStateQuietReverse (e->sref, s);
5513         }
5514       else
5515         {
5516           e->sref = sRef_saveCopy (s);
5517         }
5518     }
5519 }
5520
5521 ctype
5522 uentry_getAbstractType (uentry e)
5523 {
5524   llassert (uentry_isDatatype (e));
5525
5526   /*
5527   ** This assertion removed.
5528   ** Okay to have undefined type, for system types
5529   
5530   llassertprintret (!ctype_isUndefined (e->info->datatype->type),
5531                     ("uentry_getAbstractType %q: undefined", uentry_unparseFull (e)),
5532                     e->utype);
5533                     
5534   */
5535
5536   if (ctype_isUndefined (e->info->datatype->type))
5537     {
5538       return ctype_unknown;
5539     }
5540
5541   /*
5542   ** Sadly, a kludge...
5543   */
5544
5545   if (ctype_isUserBool (e->info->datatype->type)) {
5546     return ctype_bool;
5547   }
5548
5549   return e->info->datatype->type;
5550 }
5551
5552 ctype uentry_getRealType (uentry e)
5553 {
5554   ctype ct;
5555   typeId uid = USYMIDINVALID;
5556
5557   if (uentry_isInvalid (e))
5558     {
5559       return ctype_unknown;
5560     }
5561
5562   llassertprint (uentry_isDatatype (e), ("not datatype: %s", uentry_unparse (e)));
5563
5564   if (uentry_isAnyTag (e))
5565     {
5566       return (e->utype);
5567     }
5568   
5569   if (uentry_isAbstractType (e))
5570     {
5571       ct = uentry_getAbstractType (e);      
5572
5573       if (ctype_isManifestBool (ct)) {
5574         return ct;
5575       }
5576
5577       llassert (ctype_isUA (ct));
5578       
5579       uid = ctype_typeId (ct);
5580       
5581       if (!context_hasAccess (uid))
5582         {
5583           return (ct);
5584         }
5585     }
5586
5587   ct = uentry_getType (e);
5588
5589   /* if (ctype_isUserBool (ct)) return ct; */
5590
5591   if (ctype_isManifestBool (ct)) {
5592     return ctype_bool;
5593   }
5594   
5595   if (ctype_isUA (ct))
5596     {
5597       usymId iid = ctype_typeId (ct);
5598       
5599       if /*@access usymId@*/ (iid == uid) /*@noaccess usymId@*/
5600         {         
5601           llcontbug (message ("uentry_getRealType: recursive type! %s",
5602                               ctype_unparse (ct)));
5603           return ct;
5604         }
5605       else
5606         {
5607           /* evs 2000-07-25: possible infinite recursion ? */
5608           uentry ue2 = usymtab_getTypeEntry (iid);
5609           llassertprint (ue2 != e, ("Bad recursion: %s", uentry_unparseFull (e)));
5610
5611           return uentry_getRealType (ue2);
5612         }
5613     }
5614   else
5615     {
5616       return ct;
5617     }
5618 }
5619
5620 ctype uentry_getForceRealType (uentry e)
5621 {
5622   ctype   ct;
5623   typeId uid = USYMIDINVALID;
5624
5625   if (uentry_isInvalid (e))
5626     {
5627       return ctype_unknown;
5628     }
5629
5630   llassertprint (uentry_isDatatype (e), ("not datatype: %s", uentry_unparse (e)));
5631   
5632   if (uentry_isAnyTag (e))
5633     {
5634       return (e->utype);
5635     }
5636   
5637   if (uentry_isAbstractType (e))
5638     {
5639       ct = uentry_getAbstractType (e);      
5640       llassert (ctype_isUA (ct));
5641       
5642       uid = ctype_typeId (ct);
5643       /* no check for access! */
5644     }
5645   
5646   ct = uentry_getType (e);
5647
5648   /* evs 2000-07-25 */
5649   /* if (ctype_isUserBool (ct)) return ct; */
5650
5651   if (ctype_isManifestBool (ct)) {
5652     return ctype_bool;
5653   }
5654   
5655   if (ctype_isUA (ct))
5656     {
5657       usymId iid = ctype_typeId (ct);
5658       
5659       if /*@access usymId@*/ (iid == uid) /*@noaccess usymId@*/
5660         {         
5661           llcontbug (message ("uentry_getRealType: recursive type! %s",
5662                               ctype_unparse (ct)));
5663           return ct;
5664         }
5665       else
5666         {
5667           return uentry_getForceRealType (usymtab_getTypeEntry (iid));
5668         }
5669     }
5670   else
5671     {
5672       return ct;
5673     }
5674 }
5675
5676 uentry uentry_nameCopy (cstring name, uentry e)
5677 {
5678   uentry enew = uentry_alloc ();
5679
5680   llassert (uentry_isValid (e));
5681
5682   /* enew->shallowCopy = FALSE; */
5683   enew->ukind = e->ukind;
5684   enew->uname = name;
5685   enew->utype = e->utype;
5686   enew->whereSpecified = fileloc_copy (e->whereSpecified);
5687   enew->whereDefined = fileloc_copy (e->whereDefined);
5688   enew->whereDeclared = fileloc_copy (e->whereDeclared);
5689   enew->sref = sRef_copy (e->sref); 
5690   enew->used = e->used;
5691   enew->lset = FALSE;
5692   enew->isPrivate = e->isPrivate;
5693   enew->hasNameError = FALSE;
5694
5695   enew->uses = filelocList_new ();
5696
5697   enew->storageclass = e->storageclass;
5698   enew->info = uinfo_copy (e->info, e->ukind);
5699
5700   return enew;
5701 }
5702
5703 void
5704 uentry_setDatatype (uentry e, usymId uid)
5705 {
5706   llassert (uentry_isDatatype (e));
5707
5708   if (uentry_isAbstractType (e))
5709     {
5710       e->info->datatype->type = ctype_createAbstract (uid);
5711     }
5712   else
5713     {
5714       e->info->datatype->type = ctype_createUser (uid);
5715     }
5716 }
5717
5718 static void 
5719 uentry_setSpecDef (/*@special@*/ uentry e, /*@keep@*/ fileloc f)
5720    /*@defines e->whereSpecified, e->whereDeclared, e->whereDefined@*/
5721    /*@modifies e@*/
5722 {
5723   llassert (uentry_isValid (e));
5724
5725   if (fileloc_isSpec (f) || fileloc_isImport (f))
5726     {
5727       e->whereSpecified = f;
5728       e->whereDeclared  = fileloc_undefined;
5729       e->whereDefined  = fileloc_undefined;
5730     }
5731   else
5732     {
5733       e->whereSpecified = fileloc_undefined;
5734       e->whereDeclared  = f;
5735       e->whereDefined  = fileloc_undefined;
5736     }
5737 }
5738
5739 static void
5740 ucinfo_free (/*@only@*/ ucinfo u)
5741 {
5742   multiVal_free (u->val);
5743   sfree (u);
5744 }
5745
5746 static void
5747 uvinfo_free (/*@only@*/ uvinfo u)
5748 {
5749   sfree (u);
5750 }
5751
5752 static void
5753 udinfo_free (/*@only@*/ udinfo u)
5754 {
5755   sfree (u);
5756 }
5757
5758 static void
5759 ufinfo_free (/*@only@*/ ufinfo u)
5760 {
5761   globSet_free (u->globs);
5762   sRefSet_free (u->mods);
5763   specialClauses_free (u->specclauses);
5764
5765   sfree (u);
5766 }
5767
5768 static void
5769 uiinfo_free (/*@only@*/ uiinfo u)
5770 {
5771   sfree (u);
5772 }
5773
5774 static void
5775 ueinfo_free (/*@only@*/ ueinfo u)
5776 {
5777   sfree (u);
5778 }
5779
5780 static /*@only@*/ ucinfo
5781 ucinfo_copy (ucinfo u)
5782 {
5783   ucinfo ret = (ucinfo) dmalloc (sizeof (*ret));
5784   
5785   ret->val = multiVal_copy (u->val);
5786   ret->access = u->access;
5787
5788   return ret;
5789 }
5790
5791 static /*@only@*/ uvinfo
5792 uvinfo_copy (uvinfo u)
5793 {
5794   uvinfo ret = (uvinfo) dmalloc (sizeof (*ret));
5795   
5796   ret->kind = u->kind;
5797   ret->nullstate = u->nullstate;
5798   ret->defstate = u->defstate;
5799   ret->checked = u->checked;
5800
5801   return ret;
5802 }
5803
5804 static /*@only@*/ udinfo
5805 udinfo_copy (udinfo u)
5806 {
5807   udinfo ret = (udinfo) dmalloc (sizeof (*ret));
5808
5809   ret->abs = u->abs;
5810   ret->mut = u->mut;
5811   ret->type = u->type;
5812
5813   return ret;
5814 }
5815
5816 static /*@only@*/ ufinfo
5817 ufinfo_copy (ufinfo u)
5818 {
5819   ufinfo ret = (ufinfo) dmalloc (sizeof (*ret));
5820
5821   ret->hasGlobs = u->hasGlobs;
5822   ret->hasMods = u->hasMods;
5823   ret->exitCode = u->exitCode;
5824   ret->specialCode = u->specialCode;
5825   ret->nullPred = u->nullPred;
5826   ret->access = u->access;
5827   ret->globs = globSet_newCopy (u->globs);
5828   ret->mods = sRefSet_newCopy (u->mods);
5829   ret->defparams = u->defparams;
5830   ret->specclauses = specialClauses_copy (u->specclauses);
5831
5832   return ret;
5833 }
5834
5835 static /*@only@*/ uiinfo
5836 uiinfo_copy (uiinfo u)
5837 {
5838   uiinfo ret = (uiinfo) dmalloc (sizeof (*ret));
5839
5840   ret->access = u->access;
5841   ret->globs = globSet_newCopy (u->globs);
5842   ret->mods = sRefSet_newCopy (u->mods);
5843
5844   return (ret);
5845 }
5846
5847 static /*@only@*/ ueinfo
5848 ueinfo_copy (ueinfo u)
5849 {
5850   ueinfo ret = (ueinfo) dmalloc (sizeof (*ret));
5851
5852   ret->access = u->access;
5853   return ret;
5854 }
5855
5856 static void
5857 uinfo_free (uinfo u, ekind kind)
5858 {
5859   switch (kind)
5860     {
5861     case KENUMCONST:
5862     case KCONST:       ucinfo_free (u->uconst); break;
5863     case KVAR:         uvinfo_free (u->var); break;
5864     case KSTRUCTTAG:
5865     case KUNIONTAG:
5866     case KENUMTAG:
5867     case KDATATYPE:    udinfo_free (u->datatype); break;
5868     case KFCN:         ufinfo_free (u->fcn); break;
5869     case KITER:        uiinfo_free (u->iter); break;
5870     case KENDITER:     ueinfo_free (u->enditer); break;
5871     case KELIPSMARKER: break;
5872     case KINVALID:     break;
5873     }
5874   
5875     sfree (u);
5876 }
5877
5878 static /*@only@*/ /*@null@*/ uinfo
5879 uinfo_copy (uinfo u, ekind kind)
5880 {
5881   if (kind == KELIPSMARKER || kind == KINVALID)
5882     {
5883       return NULL;
5884     }
5885   else
5886     {
5887       uinfo ret = (uinfo) dmalloc (sizeof (*ret));
5888       
5889       switch (kind)
5890         {
5891         case KENUMCONST:
5892         case KCONST:    ret->uconst = ucinfo_copy (u->uconst); break;
5893         case KVAR:      ret->var = uvinfo_copy (u->var); break;
5894         case KSTRUCTTAG:
5895         case KUNIONTAG:
5896         case KENUMTAG:
5897         case KDATATYPE: ret->datatype = udinfo_copy (u->datatype); break;
5898         case KFCN:      ret->fcn = ufinfo_copy (u->fcn); break;
5899         case KITER:     ret->iter = uiinfo_copy (u->iter); break;
5900         case KENDITER:  ret->enditer = ueinfo_copy (u->enditer); break;
5901         BADDEFAULT;
5902         }
5903       return ret;
5904     }
5905 }
5906
5907 static void
5908 uentry_reallyFree (/*@notnull@*/ /*@only@*/ uentry e)
5909 {
5910   filelocList_free (e->uses);
5911   cstring_free (e->uname);
5912   
5913   uinfo_free (e->info, e->ukind);
5914   
5915   fileloc_free (e->whereSpecified); 
5916   fileloc_free (e->whereDefined); 
5917   fileloc_free (e->whereDeclared); 
5918
5919   nuentries--;
5920   sfree (e);
5921   }
5922
5923 extern void uentry_markOwned (/*@owned@*/ uentry u)
5924 {
5925   sfreeEventually (u);
5926 }
5927
5928 void
5929 uentry_free (/*@only@*/ uentry e)
5930 {
5931   if (uentry_isValid (e) && !uentry_isElipsisMarker (e))
5932     {
5933       uentry_reallyFree (e);
5934     }
5935 }
5936
5937 /*
5938 ** For uentry's in the global or file scope
5939 */
5940
5941 void
5942 uentry_freeComplete (/*@only@*/ uentry e)
5943 {
5944   if (uentry_isValid (e) && !uentry_isElipsisMarker (e))
5945     {
5946       /*@i@*/ sRef_free (e->sref);
5947       e->sref = sRef_undefined;
5948       uentry_reallyFree (e);
5949     }
5950 }
5951
5952 /*
5953 ** requires old->kind != new->kind, old->uname = new->uname
5954 */
5955
5956 static void
5957 KindConformanceError (/*@unique@*/ uentry old, uentry unew, bool mustConform)
5958 {
5959   llassert (uentry_isValid (old));
5960   llassert (uentry_isValid (unew));
5961
5962   if (uentry_isEitherConstant (unew)
5963       && (fileloc_isPreproc (uentry_whereDeclared (old))
5964           || ctype_isUnknown (old->utype))
5965       && !uentry_isSpecified (old))
5966     {
5967       ; /* no error */
5968     }
5969   else 
5970     {
5971       if (mustConform)
5972         {
5973           if (!uentry_isDeclared (old))
5974             {
5975               if (uentry_isSpecified (old))
5976                 {
5977                   if (uentry_isSpecified (unew))
5978                     {
5979                       llbuglit ("Respecification!");
5980                     }
5981                   else if (uentry_isDeclared (unew))
5982                     {
5983                       if (optgenerror
5984                           (FLG_INCONDEFS,
5985                            message ("%s %q inconsistently declared as %s: %t",
5986                                     ekind_capName (old->ukind),
5987                                     uentry_getName (unew),
5988                                     ekind_unparseLong (unew->ukind),
5989                                     unew->utype),
5990                            uentry_whereDeclared (unew)))
5991                         {
5992                           uentry_showWhereLast (old);
5993                         }
5994                     }
5995                   else
5996                     {
5997                       BADEXIT;
5998                     }
5999                 }
6000               else
6001                 {
6002                   if (optgenerror
6003                       (FLG_INCONDEFS,
6004                        message ("%s %q inconsistently declared as %s: %t",
6005                                 ekind_capName (old->ukind),
6006                                 uentry_getName (unew),
6007                                 ekind_unparseLong (unew->ukind),
6008                                 unew->utype),
6009                        uentry_whereDeclared (unew)))
6010                     {
6011                       uentry_showWhereLast (old);
6012                     }
6013                 }
6014             }
6015           else
6016             {
6017               llassert (uentry_isDeclared (unew));
6018
6019               if (optgenerror
6020                   (FLG_INCONDEFS,
6021                    message ("%s %q inconsistently redeclared as %s",
6022                             ekind_capName (old->ukind),
6023                             uentry_getName (unew),
6024                             ekind_unparseLong (unew->ukind)),
6025                    uentry_whereDeclared (unew)))
6026                 {
6027                   uentry_showWhereLast (old);
6028                 }
6029             }
6030         }
6031     }
6032
6033   uentry_copyInto (old, unew);
6034 }
6035
6036 /*
6037 ** def is the definition of spec, modifies spec
6038 **
6039 ** reports any inconsistencies
6040 ** returns the summary of all available information
6041 ** if spec and def are inconsistent, def is returned
6042 */
6043
6044 void
6045 uentry_showWhereLast (uentry spec)
6046 {
6047   if (uentry_isValid (spec))
6048     {
6049       if (fileloc_isDefined (spec->whereDefined)
6050           && !fileloc_isLib (spec->whereDefined)
6051           && !fileloc_isPreproc (spec->whereDefined))
6052         {
6053           llgenindentmsg (message ("Previous definition of %q: %t", 
6054                                    uentry_getName (spec),
6055                                    uentry_getType (spec)),
6056                           uentry_whereDefined (spec));
6057         }
6058       else if (uentry_isDeclared (spec))
6059         {
6060           llgenindentmsg (message ("Previous declaration of %q: %t", 
6061                                    uentry_getName (spec),
6062                                    uentry_getType (spec)),
6063                           uentry_whereDeclared (spec));
6064         }
6065       else if (uentry_isSpecified (spec))
6066         {
6067           if (uentry_hasName (spec))
6068             {
6069               llgenindentmsg (message ("Specification of %q: %t", 
6070                                        uentry_getName (spec),
6071                                        uentry_getType (spec)),
6072                               uentry_whereSpecified (spec));
6073             }
6074           else
6075             {
6076               llgenindentmsg (message ("Specification: %t", uentry_getType (spec)),
6077                               uentry_whereSpecified (spec));
6078             }
6079         }
6080       else
6081         {
6082           /* nothing to show */
6083         }
6084     }
6085 }
6086
6087 void
6088 uentry_showDefSpecInfo (uentry ce, fileloc fwhere)
6089 {
6090   fileloc loc = uentry_whereDefined (ce);
6091   
6092   if (fileloc_isUser (loc) && !fileloc_equal (loc, fwhere))
6093     {
6094       llgenindentmsg (message ("Definition of %q", uentry_getName (ce)),
6095                       loc);
6096     }
6097
6098   loc = uentry_whereSpecified (ce);
6099   
6100   if (fileloc_isUser (loc) && !fileloc_equal (loc, fwhere))
6101     {
6102       llgenindentmsg (message ("Specification of %q", uentry_getName (ce)),
6103                       loc);
6104     }
6105 }
6106
6107 void uentry_showWhereLastExtra (uentry spec, cstring extra)
6108 {
6109   if (uentry_isDeclared (spec))
6110     {
6111       llgenindentmsg (message ("Previous declaration of %q: %q", 
6112                                uentry_getName (spec), extra),
6113                       uentry_whereDeclared (spec));
6114     }
6115   else if (uentry_isSpecified (spec))
6116     {
6117       llgenindentmsg (message ("Specification of %q: %q", 
6118                                uentry_getName (spec), extra),
6119                       uentry_whereSpecified (spec));
6120     }
6121   else
6122     {
6123       cstring_free (extra);
6124     }
6125 }
6126
6127 void
6128 uentry_showWhereDeclared (uentry spec)
6129 {
6130   if (uentry_isDeclared (spec))
6131     {
6132       if (uentry_hasName (spec))
6133         {
6134           llgenindentmsg (message ("Declaration of %q", uentry_getName (spec)),
6135                           uentry_whereDeclared (spec));
6136         }
6137       else
6138         {
6139           llgenindentmsg (cstring_makeLiteral ("Declaration"), uentry_whereDeclared (spec));
6140         }
6141     }
6142   else if (uentry_isSpecified (spec))
6143     {
6144       if (uentry_hasName (spec))
6145         {
6146           llgenindentmsg (message ("Specification of %q", uentry_getName (spec)),
6147                           uentry_whereSpecified (spec));
6148         }
6149       else
6150         {
6151           llgenindentmsg (cstring_makeLiteral ("Specification"), uentry_whereSpecified (spec));
6152         }
6153     }
6154   else
6155     {
6156       /* nothing to show */
6157     }
6158     
6159 }
6160
6161 void
6162 uentry_showWhereAny (uentry spec)
6163 {
6164   if (uentry_isDeclared (spec))
6165     {
6166       if (uentry_hasName (spec))
6167         {
6168           llgenindentmsg (message ("Declaration of %q", uentry_getName (spec)),
6169                           uentry_whereDeclared (spec));
6170         }
6171       else
6172         {
6173           llgenindentmsg (cstring_makeLiteral ("Declaration"), uentry_whereDeclared (spec));
6174         }
6175     }
6176   else if (uentry_isSpecified (spec))
6177     {
6178       if (uentry_hasName (spec))
6179         {
6180           llgenindentmsg (message ("Specification of %q",
6181                                    uentry_getName (spec)),
6182                           uentry_whereSpecified (spec));
6183         }
6184       else
6185         {
6186           llgenindentmsg (cstring_makeLiteral ("Specification"), 
6187                           uentry_whereSpecified (spec));
6188         }
6189     }
6190   else if (fileloc_isDefined (uentry_whereDefined (spec))) 
6191     {
6192       if (uentry_hasName (spec))
6193         {
6194           llgenindentmsg (message ("Definition of %q", uentry_getName (spec)),
6195                           uentry_whereDefined (spec));
6196         }
6197       else
6198         {
6199           llgenindentmsg (cstring_makeLiteral ("Definition"), uentry_whereDefined (spec));
6200         }
6201     }
6202   else
6203     {
6204       /* nothing to show */
6205     }
6206 }
6207
6208 void
6209 uentry_showWhereDefined (uentry spec)
6210 {
6211   if (uentry_isCodeDefined (spec))
6212     {
6213       llgenindentmsg (message ("Previous definition of %q", uentry_getName (spec)),
6214                       uentry_whereDefined (spec));
6215     }
6216 }
6217
6218 void
6219 uentry_showWhereLastPlain (uentry spec)
6220 {
6221   if (uentry_isDeclared (spec))
6222     {
6223       llgenindentmsg (message ("Previous declaration of %q", uentry_getName (spec)),
6224                       uentry_whereDeclared (spec));
6225     }
6226   else if (uentry_isSpecified (spec))
6227     {
6228       llgenindentmsg (message ("Specification of %q", uentry_getName (spec)),
6229                       uentry_whereSpecified (spec));
6230     }
6231   else
6232     {
6233           }
6234 }
6235
6236 static void
6237 uentry_showWhereLastVal (uentry spec, cstring val)
6238 {
6239   if (uentry_isDeclared (spec))
6240     {
6241       llgenindentmsg (message ("Previous declaration of %q: %s", 
6242                                uentry_getName (spec), val),
6243                       uentry_whereDeclared (spec));
6244     }
6245   else if (uentry_isSpecified (spec))
6246     {
6247       llgenindentmsg (message ("Specification of %q: %s", 
6248                                uentry_getName (spec), val),
6249                       uentry_whereSpecified (spec));
6250     }
6251   else
6252     {
6253     }
6254 }
6255
6256 void
6257 uentry_showWhereSpecified (uentry spec)
6258 {
6259   if (uentry_isSpecified (spec))
6260     {
6261       if (uentry_hasName (spec))
6262         {
6263           llgenindentmsg (message ("Specification of %q", uentry_getName (spec)),
6264                           uentry_whereSpecified (spec));
6265         }
6266       else
6267         {
6268           llgenindentmsg (cstring_makeLiteral ("Specification"), 
6269                           uentry_whereSpecified (spec));
6270         }
6271     }
6272   else if (uentry_isDeclared (spec))
6273     {
6274       llgenindentmsg (message ("Declaration of %q", uentry_getName (spec)),
6275                       uentry_whereDeclared (spec));
6276     }
6277   else
6278     {
6279       /* nothing to show */
6280     }
6281 }
6282
6283 void
6284 uentry_showWhereSpecifiedExtra (uentry spec, cstring s)
6285 {
6286   if (uentry_isSpecified (spec))
6287     {
6288       if (uentry_hasName (spec))
6289         {
6290           llgenindentmsg (message ("Specification of %q: %q", 
6291                                    uentry_getName (spec), s),
6292                           uentry_whereSpecified (spec));
6293         }
6294       else
6295         {
6296           llgenindentmsg (message ("Specification: %q", s), 
6297                           uentry_whereSpecified (spec));
6298         }
6299     }
6300   else if (uentry_isDeclared (spec))
6301     {
6302       llgenindentmsg (message ("Declaration of %q: %q", 
6303                                uentry_getName (spec), s),
6304                       uentry_whereDeclared (spec));
6305     }
6306   else
6307     {
6308       llgenindentmsg (message ("Previous: %q", s),
6309                       uentry_whereLast (spec));
6310     }
6311 }
6312
6313 /*
6314 **
6315 */
6316
6317 static void
6318 checkStructConformance (uentry old, uentry unew)
6319 {
6320   ctype oldr, newr; 
6321   uentryList fold, fnew;
6322
6323   /*
6324   ** requires: types of old and new are structs or unions
6325   */
6326
6327   llassert (uentry_isValid (old));
6328   llassert (uentry_isValid (unew));
6329
6330   oldr = ctype_realType (old->utype);
6331   fold =  ctype_getFields (oldr);
6332
6333   newr = ctype_realType (unew->utype);
6334   fnew = ctype_getFields (newr);
6335
6336   if (!uentryList_matchFields (fold, fnew))
6337     {
6338       if (fileloc_equal (uentry_whereLast (old),
6339                          uentry_whereLast (unew)))
6340         {
6341           ; /* cheat! */
6342         }
6343       else 
6344         {
6345           if (optgenerror 
6346               (FLG_MATCHFIELDS,
6347                message ("%q %q %rdeclared with fields { %q }, %s "
6348                         "with fields { %q }",
6349                         cstring_makeLiteral (ctype_isStruct (newr) ? "Structure": "Union"),
6350                         uentry_getName (old), 
6351                         uentry_isDeclared (old),
6352                         uentryList_unparseAbbrev (fnew),
6353                         uentry_specOrDefName (old),
6354                         uentryList_unparseAbbrev (fold)),
6355                uentry_whereDeclared (unew)))
6356             {
6357               uentry_showWhereLastPlain (old);
6358               uentryList_showFieldDifference (fold, fnew);
6359             }
6360         }
6361
6362       old->utype = unew->utype;
6363     }
6364 }
6365
6366 static void
6367 checkEnumConformance (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew)
6368 {
6369   /*
6370   ** requires old and new are enums
6371   */
6372   
6373   ctype        rold = ctype_realType (old->utype);
6374   ctype        rnew = ctype_realType (unew->utype);
6375   enumNameList eold = ctype_elist (rold);
6376   enumNameList enew = ctype_elist (rnew);
6377   
6378   if (!enumNameList_match (eold, enew))
6379     {
6380       if (optgenerror 
6381           (FLG_MATCHFIELDS,
6382            message ("Enum %q declared with members { %q } but "
6383                     "specified with members { %q }",
6384                     uentry_getName (old), 
6385                     enumNameList_unparse (enew),
6386                     enumNameList_unparse (eold)),
6387            uentry_whereDeclared (unew)))
6388         {
6389           uentry_showWhereSpecified (old);
6390           old->utype = unew->utype;
6391         }
6392     }
6393 }
6394
6395 /*
6396 ** either oldCurrent or newCurrent may be undefined!
6397 */
6398
6399 static void
6400 paramTypeError (uentry old, uentry oldCurrent, ctype oldType,
6401                 uentry unew, uentry newCurrent, ctype newType,
6402                 int paramno)
6403 {
6404   bool hasError = FALSE;
6405
6406   if (uentry_isValid (newCurrent) && uentry_isDeclared (newCurrent))
6407     {
6408       if (uentry_hasName (newCurrent))
6409         {
6410           hasError = optgenerror 
6411             (FLG_TYPE,
6412              message ("Parameter %d, %q, of function %q has inconsistent type: "
6413                       "declared %t, %s %t",
6414                       paramno + 1, uentry_getName (newCurrent), 
6415                       uentry_getName (unew),
6416                       newType, uentry_specOrDefName (old), oldType),
6417              uentry_whereDeclared (newCurrent));
6418         }
6419       else
6420         {
6421           hasError = optgenerror
6422             (FLG_TYPE,
6423              message ("Parameter %d of function %q has inconsistent type: "
6424                       "declared %t, %s %t",
6425                       paramno + 1, uentry_getName (unew),
6426                       newType, uentry_specOrDefName (old), oldType),
6427              uentry_whereDeclared (newCurrent));
6428
6429           DPRINTF (("type: %s / %s",
6430                     ctype_unparse (newType),
6431                     ctype_unparse (ctype_realType (newType))));
6432         }
6433     }
6434   else 
6435     {
6436       if (uentry_isDeclared (unew))
6437         {
6438           hasError = optgenerror 
6439             (FLG_TYPE,
6440              message ("Parameter %d of function %s has inconsistent type: "
6441                       "declared %t, %s %t",
6442                       paramno + 1, unew->uname, 
6443                       newType, uentry_specOrDefName (old), oldType),
6444              uentry_whereDeclared (unew));
6445         }
6446       else
6447         {
6448           hasError = optgenerror
6449             (FLG_TYPE,
6450              message ("Parameter %d of function %s has inconsistent type: "
6451                       "declared %t, %s %t",
6452                       paramno + 1, unew->uname, 
6453                       newType, uentry_specOrDefName (old), oldType),
6454              uentry_whereDeclared (unew));
6455         }
6456     }
6457   
6458   if (hasError)
6459     {
6460       if (!uentry_isUndefined (oldCurrent))
6461         {
6462           if (!uentry_isUndefined (newCurrent) 
6463               && cstring_equal (uentry_rawName (newCurrent), uentry_rawName (oldCurrent)))
6464             {
6465               uentry_showWhereLast (oldCurrent);
6466             }
6467           else
6468             {
6469               uentry_showWhereLastPlain (old);
6470             }
6471           
6472           uentry_setType (oldCurrent, newType);
6473         }
6474       else
6475         {
6476           uentry_showWhereLastPlain (old);
6477         }
6478     }
6479 }
6480
6481 static void
6482 nargsError (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew)
6483 {
6484   if (optgenerror 
6485       (FLG_TYPE,
6486        message ("Function %s %rdeclared with %d arg%p, %s with %d",
6487                 unew->uname, 
6488                 uentry_isDeclared (old),
6489                 uentryList_size (uentry_getParams (unew)),
6490                 uentry_specOrDefName (old),
6491                 uentryList_size (uentry_getParams (old))),
6492        uentry_whereDeclared (unew)))
6493     {
6494       uentry_showWhereLastPlain (old);
6495     }
6496 }
6497
6498 static void
6499 returnValueError (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew)
6500 {
6501   if (optgenerror
6502       (FLG_INCONDEFS,
6503        message ("Function %s inconsistently %rdeclared to return %t",
6504                 unew->uname,
6505                 uentry_isDeclared (old),
6506                 ctype_returnValue (unew->utype)),
6507        uentry_whereDeclared (unew)))
6508     {
6509       uentry_showWhereLastVal (old, ctype_unparse (ctype_returnValue (old->utype)));
6510     }
6511 }
6512
6513 static cstring paramStorageName (uentry ue)
6514 {
6515   return (cstring_makeLiteralTemp (uentry_isParam (ue) ? "param" : "storage"));
6516 }
6517
6518 static cstring fcnErrName (uentry ue)
6519 {
6520   return (cstring_makeLiteralTemp (uentry_isFunction (ue) ? "to return" : "as"));
6521 }
6522
6523 extern /*@observer@*/ cstring uentry_checkedName (uentry ue)
6524 {
6525   if (uentry_isVar (ue))
6526     {
6527       return (checkedName (ue->info->var->checked));
6528     }
6529   else
6530     {
6531       return (cstring_makeLiteralTemp ("<checked invalid>"));
6532     }
6533 }
6534
6535 static cstring checkedName (chkind checked)
6536 {
6537   switch (checked)
6538     {
6539     case CH_UNKNOWN:       return (cstring_makeLiteralTemp ("unknown"));
6540     case CH_UNCHECKED:     return (cstring_makeLiteralTemp ("unchecked"));
6541     case CH_CHECKED:       return (cstring_makeLiteralTemp ("checked"));
6542     case CH_CHECKMOD:      return (cstring_makeLiteralTemp ("checkmod"));
6543     case CH_CHECKEDSTRICT: return (cstring_makeLiteralTemp ("checkedstrict"));
6544     }
6545   BADEXIT;
6546 }
6547
6548 static
6549 void checkNullState (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew, bool mustConform, bool completeConform)
6550 {
6551   nstate oldState;
6552   nstate newState;
6553   
6554   if (uentry_isVar (unew))
6555     {
6556       llassert (uentry_isVar (old));
6557       
6558       oldState = old->info->var->nullstate;
6559       newState = unew->info->var->nullstate;
6560     }
6561   else
6562     {
6563       oldState = sRef_getNullState (old->sref);
6564       newState = sRef_getNullState (unew->sref);
6565     }
6566
6567   if (oldState == NS_ABSNULL)
6568     {
6569       if (uentry_isVar (old))
6570         {
6571           old->info->var->nullstate = newState;
6572         }
6573       
6574       sRef_mergeNullState (old->sref, newState);
6575     }
6576   else if (newState == NS_UNKNOWN)
6577     {
6578       if (completeConform && newState != oldState
6579           && uentry_isReallySpecified (old))
6580         {
6581           if (optgenerror 
6582               (FLG_NEEDSPEC,
6583                message ("%s %q specified as %s, but declared without %s qualifier",
6584                         ekind_capName (unew->ukind),
6585                         uentry_getName (unew),
6586                         nstate_unparse (oldState),
6587                         nstate_unparse (oldState)),
6588                uentry_whereDeclared (unew)))
6589             {
6590               uentry_showWhereSpecified (old);
6591             }
6592         }
6593       
6594       if (uentry_isVar (unew))
6595         {
6596           unew->info->var->nullstate = oldState;
6597         }
6598
6599       sRef_mergeNullState (unew->sref, oldState);
6600     }
6601   else if (newState == NS_POSNULL)
6602     {
6603       if (oldState == NS_MNOTNULL 
6604           && (ctype_isUA (unew->utype) 
6605               || (uentry_isFunction (unew)
6606                   && ctype_isUA (ctype_returnValue (unew->utype)))))
6607         {
6608           if (uentry_isVar (unew))
6609             {
6610               unew->info->var->nullstate = oldState;
6611             }
6612
6613           sRef_mergeNullState (unew->sref, oldState);
6614         }
6615       else 
6616         {
6617           if (oldState == NS_NOTNULL || oldState == NS_MNOTNULL 
6618               || oldState == NS_UNKNOWN)
6619             {
6620               if (mustConform)
6621                 {
6622                   if (optgenerror 
6623                       (FLG_INCONDEFS,
6624                        message 
6625                        ("%s %q inconsistently %rdeclared %s possibly null storage, "
6626                         "%s %q qualifier",
6627                         uentry_ekindName (unew),
6628                         uentry_getName (unew),
6629                         uentry_isDeclared (old),
6630                         fcnErrName (unew),
6631                         uentry_specOrDefName (old),
6632                         cstring_makeLiteral (oldState == NS_MNOTNULL ? "with notnull" : "without null")),
6633                        uentry_whereDeclared (unew)))
6634                     {
6635                       uentry_showWhereSpecified (old);
6636                     }
6637                 }
6638             }
6639           
6640           if (uentry_isVar (old))
6641             {
6642               old->info->var->nullstate = newState;
6643             }
6644
6645           sRef_mergeNullState (old->sref, newState);
6646         }
6647     }
6648   else if (newState == NS_MNOTNULL)
6649     {
6650       if (oldState != NS_MNOTNULL)
6651         {
6652           if (mustConform)
6653             {
6654               if (optgenerror 
6655                   (FLG_INCONDEFS,
6656                    message ("%s %q inconsistently %rdeclared %s notnull storage, "
6657                             "%s without notnull qualifier",
6658                             uentry_ekindName (unew),
6659                             uentry_getName (unew),
6660                             uentry_isDeclared (old),
6661                             fcnErrName (unew),
6662                             uentry_specOrDefName (old)),
6663                    uentry_whereDeclared (unew)))
6664                 {
6665                   uentry_showWhereSpecified (old);
6666                 }
6667             }
6668           
6669           if (uentry_isVar (old))
6670             {
6671               old->info->var->nullstate = newState;
6672             }
6673
6674           sRef_mergeNullState (old->sref, newState);
6675         }
6676     }
6677   else
6678     {
6679       if (uentry_isVar (unew)) 
6680         {
6681           unew->info->var->nullstate = oldState;
6682         }
6683
6684       sRef_mergeNullState (unew->sref, oldState);
6685     }
6686 }
6687
6688 static
6689 void checkDefState (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew, 
6690                     bool mustConform, bool completeConform)
6691 {
6692   sstate oldState;
6693   sstate newState;
6694   bool vars = FALSE;
6695
6696   if (uentry_isVar (old) && uentry_isVar (unew))
6697     {
6698       oldState = old->info->var->defstate;
6699       newState = unew->info->var->defstate;
6700       vars = TRUE;
6701     }
6702   else
6703     {
6704       oldState = sRef_getDefState (old->sref);
6705       newState = sRef_getDefState (unew->sref);
6706     }
6707
6708   if (newState != oldState && newState != SS_UNKNOWN && newState != SS_DEFINED)
6709     {
6710       if (mustConform)
6711         {
6712           if (optgenerror 
6713               (FLG_INCONDEFS,
6714                message ("%s %q inconsistently %rdeclared %s %s %s, "
6715                         "%s %s %s %s",
6716                         uentry_ekindName (unew),
6717                         uentry_getName (unew),
6718                         uentry_isDeclared (old),
6719                         fcnErrName (unew),
6720                         sstate_unparse (newState),
6721                         paramStorageName (unew),
6722                         uentry_specOrDefName (old),
6723                         fcnErrName (unew),
6724                         sstate_unparse (oldState),
6725                         paramStorageName (unew)),
6726                uentry_whereDeclared (unew)))
6727             {
6728               uentry_showWhereSpecified (old);
6729             }
6730         }
6731       
6732       if (vars) old->info->var->defstate = newState;
6733       sRef_setDefState (old->sref, newState, uentry_whereDeclared (unew));
6734     }
6735   else
6736     {
6737       if (completeConform
6738           && (newState != oldState) && (oldState != SS_DEFINED)
6739           && uentry_isReallySpecified (old))
6740         {
6741           if (optgenerror 
6742               (FLG_NEEDSPEC,
6743                message ("%s %q specified as %s, but declared without %s qualifier",
6744                         ekind_capName (unew->ukind),
6745                         uentry_getName (unew),
6746                         sstate_unparse (oldState),
6747                         sstate_unparse (oldState)),
6748                uentry_whereDeclared (unew)))
6749             {
6750               uentry_showWhereSpecified (old);
6751             }
6752         }
6753
6754       if (vars) unew->info->var->defstate = oldState;
6755       sRef_setDefState (unew->sref, oldState, uentry_whereDeclared (unew));
6756     }
6757 }
6758
6759 static void 
6760   checkAliasState (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew, 
6761                    bool mustConform, bool completeConform)
6762 {
6763   alkind newKind;
6764   alkind oldKind;
6765
6766   oldKind = sRef_getAliasKind (old->sref);
6767   newKind = sRef_getAliasKind (unew->sref);
6768
6769   if (alkind_isImplicit (newKind) 
6770       || (alkind_isRefCounted (newKind) && !uentry_isDatatype (unew)))
6771     {
6772       if (completeConform && !alkind_equal (newKind, oldKind)
6773           && uentry_isReallySpecified (old))
6774         {
6775           if (optgenerror 
6776               (FLG_NEEDSPEC,
6777                message ("%s %q specified as %s, but declared without "
6778                         "explicit alias qualifier",
6779                         ekind_capName (unew->ukind),
6780                         uentry_getName (unew),
6781                         alkind_unparse (oldKind)),
6782                uentry_whereDeclared (unew)))
6783             {
6784               uentry_showWhereSpecified (old);
6785             }
6786         }
6787
6788       /*  
6789       ** This really shouldn't be necessary, but it is!
6790       ** Function params (?) use new here.
6791       */
6792
6793       sRef_setAliasKind (unew->sref, oldKind, uentry_whereDeclared (unew));
6794       return;
6795     }
6796
6797   if (alkind_isKnown (newKind))
6798     {
6799       if (!alkind_equal (oldKind, newKind))
6800         {
6801           if (alkind_isKnown (oldKind))
6802             {
6803               if (mustConform && 
6804                   optgenerror 
6805                   (FLG_INCONDEFS,
6806                    message ("%s %q inconsistently %rdeclared %s %s storage, "
6807                             "%s as %s storage",
6808                             uentry_ekindName (unew),
6809                             uentry_getName (unew),
6810                             uentry_isDeclared (old),
6811                             fcnErrName (unew),
6812                             alkind_unparse (newKind),
6813                             uentry_specOrDefName (old),
6814                             alkind_unparse (oldKind)),
6815                    uentry_whereDeclared (unew)))
6816                 {
6817                   uentry_showWhereSpecified (old);
6818
6819                   sRef_setAliasKind (old->sref, AK_ERROR, 
6820                                      uentry_whereDeclared (unew));
6821                 }
6822               else
6823                 {
6824                   sRef_setAliasKind (old->sref, newKind, 
6825                                      uentry_whereDeclared (unew));
6826                 }
6827             }
6828           else
6829             {
6830               if (!(alkind_isImplicit (newKind)))
6831                 {
6832                   if (mustConform &&
6833                       !uentry_isFunction (unew) &&
6834                       optgenerror 
6835                       (FLG_INCONDEFS,
6836                        message ("%s %q inconsistently %rdeclared %s %s storage, "
6837                                 "implicitly %s as temp storage",
6838                                 uentry_ekindName (unew),
6839                                 uentry_getName (unew),
6840                                 uentry_isDeclared (old),
6841                                 fcnErrName (unew),
6842                                 alkind_unparse (newKind),
6843                                 uentry_specOrDefName (old)),
6844                        uentry_whereDeclared (unew)))
6845                     {
6846                       uentry_showWhereSpecified (old);
6847                       oldKind = AK_ERROR;
6848                     }
6849                   
6850                   sRef_setAliasKind (old->sref, newKind, 
6851                                      uentry_whereDeclared (unew));
6852                 }
6853               else /* newKind is temp or refcounted */
6854                 {
6855                   ;
6856                 }
6857             }
6858         }
6859     }
6860   else /* newKind unknown */
6861     {
6862       ;
6863     }
6864 }
6865
6866 static void 
6867   checkExpState(/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew, 
6868                 bool mustConform, bool completeConform)
6869 {
6870   exkind newKind;
6871   exkind oldKind;
6872   
6873   oldKind = sRef_getExKind (old->sref);
6874   newKind = sRef_getExKind (unew->sref);
6875
6876   if (exkind_isKnown (newKind))
6877     {
6878       if (oldKind != newKind)
6879         {
6880           if (exkind_isKnown (oldKind))
6881             {
6882               if (mustConform && 
6883                   optgenerror 
6884                   (FLG_INCONDEFS,
6885                    message ("%s %q inconsistently %rdeclared %s %s, %s as %s",
6886                             uentry_ekindName (unew),
6887                             uentry_getName (unew),
6888                             uentry_isDeclared (old),
6889                             fcnErrName (unew),
6890                             exkind_unparse (newKind),
6891                             uentry_specOrDefName (old),
6892                             exkind_unparse (oldKind)),
6893                    uentry_whereDeclared (unew)))
6894                 {
6895                   uentry_showWhereSpecified (old);
6896                 }
6897
6898               sRef_setExKind (old->sref, newKind, uentry_whereDefined (unew));
6899             }
6900           else
6901             {
6902               if (mustConform &&
6903                   optgenerror 
6904                   (FLG_INCONDEFS,
6905                    message ("%s %q inconsistently %rdeclared %s %s, "
6906                             "implicitly %s without exposure qualifier",
6907                             uentry_ekindName (unew),
6908                             uentry_getName (unew),
6909                             uentry_isDeclared (old),
6910                             fcnErrName (unew),
6911                             exkind_unparse (newKind),
6912                             uentry_specOrDefName (old)),
6913                    uentry_whereDeclared (unew)))
6914                 {
6915                   uentry_showWhereSpecified (old);
6916                 }
6917
6918               sRef_setExKind (old->sref, newKind, uentry_whereDefined (unew));
6919             }
6920         }
6921     }
6922   else
6923     {
6924       if (completeConform && exkind_isKnown (oldKind)
6925           && uentry_isReallySpecified (old))
6926         {
6927           if (optgenerror 
6928               (FLG_NEEDSPEC,
6929                message ("%s %q specified as %s, but declared without "
6930                         "exposure qualifier",
6931                         ekind_capName (unew->ukind),
6932                         uentry_getName (unew),
6933                         exkind_unparse (oldKind)),
6934                uentry_whereDeclared (unew)))
6935             {
6936               uentry_showWhereSpecified (old);
6937             }
6938         }
6939
6940       /* yes, this is necessary! (if its a param) */
6941       sRef_setExKind (unew->sref, oldKind, fileloc_undefined);
6942     }
6943 }
6944
6945 static void
6946 uentry_checkStateConformance (/*@notnull@*/ uentry old,
6947                               /*@notnull@*/ uentry unew,
6948                               bool mustConform, bool completeConform)
6949 {
6950   checkDefState (old, unew, mustConform, completeConform);
6951   checkNullState (old, unew, mustConform, completeConform);
6952   checkAliasState (old, unew, mustConform, completeConform);
6953   checkExpState (old, unew, mustConform, completeConform);
6954
6955   sRef_storeState (old->sref);
6956   sRef_storeState (unew->sref);
6957 }
6958
6959 static void
6960 checkVarConformance (uentry old, uentry unew, bool mustConform, bool completeConform)
6961 {
6962   if (uentry_isElipsisMarker (old) || uentry_isElipsisMarker (unew))
6963     {
6964       return;
6965     }
6966
6967   llassert (uentry_isVar (old));
6968   llassert (uentry_isVar (unew));
6969
6970   if (cstring_isEmpty (old->uname)) 
6971     {
6972       cstring_free (old->uname);
6973       old->uname = cstring_copy (unew->uname);
6974     }
6975
6976   if (unew->info->var->kind == VKRETPARAM
6977       || unew->info->var->kind == VKSEFRETPARAM)
6978     {
6979       if (old->info->var->kind != VKRETPARAM
6980           && old->info->var->kind != VKSEFRETPARAM)
6981         {
6982           if (optgenerror 
6983               (FLG_INCONDEFS,
6984                message ("Parameter %q inconsistently %rdeclared as "
6985                         "returned parameter",
6986                         uentry_getName (unew),
6987                         uentry_isDeclared (old)),
6988                uentry_whereDeclared (unew)))
6989             {
6990               uentry_showWhereSpecified (old);
6991               old->info->var->kind = unew->info->var->kind;
6992             }
6993         }
6994     }
6995
6996
6997   if (unew->info->var->kind == VKSEFPARAM || unew->info->var->kind == VKSEFRETPARAM)
6998     {
6999       if (old->info->var->kind != VKSEFPARAM 
7000           && old->info->var->kind != VKSEFRETPARAM)
7001         {
7002           if (optgenerror 
7003               (FLG_INCONDEFS,
7004                message ("Parameter %qinconsistently %rdeclared as "
7005                         "sef parameter",
7006                         uentry_getOptName (unew),
7007                         uentry_isDeclared (old)),
7008                uentry_whereDeclared (unew)))
7009             {
7010               uentry_showWhereSpecified (old);
7011               old->info->var->kind = unew->info->var->kind;
7012             }
7013         }
7014     }
7015
7016   if (old->info->var->kind == VKSPEC)
7017     {
7018       old->info->var->kind = unew->info->var->kind;
7019     }
7020   else
7021     {
7022       unew->info->var->kind = old->info->var->kind;
7023     }
7024
7025   if (unew->info->var->checked != CH_UNKNOWN
7026       && unew->info->var->checked != old->info->var->checked)
7027     {
7028       if (old->info->var->checked == CH_UNKNOWN
7029           && !fileloc_isUser (uentry_whereLast (old)))
7030         {
7031           ; /* no error */
7032         }
7033       else
7034         {
7035           if (optgenerror 
7036               (FLG_INCONDEFS,
7037                message ("Variable %q inconsistently %rdeclared as "
7038                         "%s parameter (was %s)",
7039                         uentry_getName (unew),
7040                         uentry_isDeclared (old),
7041                         checkedName (unew->info->var->checked),
7042                         checkedName (old->info->var->checked)),
7043                uentry_whereDeclared (unew)))
7044             {
7045               uentry_showWhereSpecified (old);
7046             }
7047         }
7048       
7049       old->info->var->checked = unew->info->var->checked;
7050     }
7051   else
7052     {
7053       if (completeConform 
7054           && (old->info->var->checked != CH_UNKNOWN)
7055           && uentry_isReallySpecified (old))
7056         {
7057           if (optgenerror 
7058               (FLG_NEEDSPEC,
7059                message ("%s %q specified as %s, but declared without %s qualifier",
7060                         ekind_capName (unew->ukind),
7061                         uentry_getName (unew),
7062                         checkedName (old->info->var->checked),
7063                         checkedName (old->info->var->checked)),
7064                uentry_whereDeclared (unew)))
7065             {
7066               uentry_showWhereSpecified (old);
7067             }
7068         }
7069       
7070       unew->info->var->checked = old->info->var->checked;
7071     }
7072
7073   uentry_checkStateConformance (old, unew, mustConform, completeConform);
7074 }
7075
7076 void uentry_checkMatchParam (uentry u1, uentry u2, int paramno, exprNode e)
7077 {
7078   if (uentry_isElipsisMarker (u1) || uentry_isElipsisMarker (u2))
7079     {
7080       return;
7081     }
7082
7083   llassert (uentry_isVar (u1));
7084   llassert (uentry_isVar (u2));
7085
7086   if (u1->info->var->kind != u2->info->var->kind) {
7087     if (u1->info->var->kind == VKSEFRETPARAM) {
7088       if (u2->info->var->kind == VKRETPARAM) {
7089         voptgenerror 
7090           (FLG_TYPE,
7091            message ("Function types are inconsistent. Parameter %d is "
7092                     "sef parameter, but non-sef parameter in "
7093                     "assigned function: %s",
7094                     paramno, exprNode_unparse (e)),
7095            exprNode_loc (e));
7096       } else if (u2->info->var->kind == VKSEFPARAM) {
7097         voptgenerror 
7098           (FLG_TYPE,
7099            message ("Function types are inconsistent. Parameter %d is "
7100                     "returns parameter, but non-returns parameter in "
7101                     "assigned function: %s",
7102                     paramno, exprNode_unparse (e)),
7103            exprNode_loc (e));
7104       } else {
7105         voptgenerror 
7106           (FLG_TYPE,
7107            message ("Function types are inconsistent. Parameter %d is "
7108                     "sef returns parameter, but non-sef returns parameter in "
7109                     "assigned function: %s",
7110                     paramno, exprNode_unparse (e)),
7111            exprNode_loc (e));
7112       }
7113     } else if (u1->info->var->kind == VKRETPARAM) {
7114       voptgenerror 
7115         (FLG_TYPE,
7116          message ("Function types are inconsistent. Parameter %d is "
7117                   "returns parameter, but non-returns parameter in "
7118                   "assigned function: %s",
7119                   paramno, exprNode_unparse (e)),
7120          exprNode_loc (e));
7121     } else if (u1->info->var->kind == VKSEFPARAM) {
7122       voptgenerror 
7123         (FLG_TYPE,
7124          message ("Function types are inconsistent. Parameter %d is "
7125                   "sef parameter, but non-sef parameter in "
7126                   "assigned function: %s",
7127                   paramno, exprNode_unparse (e)),
7128          exprNode_loc (e));
7129     } else {
7130       if (u2->info->var->kind == VKSEFRETPARAM) {
7131         voptgenerror 
7132           (FLG_TYPE,
7133            message ("Function types are inconsistent. Parameter %d is "
7134                     "normal parameter, but sef returns parameter in "
7135                     "assigned function: %s",
7136                     paramno, exprNode_unparse (e)),
7137            exprNode_loc (e));
7138       } else if (u2->info->var->kind == VKSEFPARAM) {
7139         voptgenerror 
7140           (FLG_TYPE,
7141            message ("Function types are inconsistent. Parameter %d is "
7142                     "normal parameter, but sef parameter in "
7143                     "assigned function: %s",
7144                     paramno, exprNode_unparse (e)),
7145            exprNode_loc (e));
7146       } else if (u2->info->var->kind == VKRETPARAM) {
7147         voptgenerror 
7148           (FLG_TYPE,
7149            message ("Function types are inconsistent. Parameter %d is "
7150                     "normal parameter, but returns parameter in "
7151                     "assigned function: %s",
7152                     paramno, exprNode_unparse (e)),
7153            exprNode_loc (e));
7154       } else {
7155         BADBRANCH;
7156       }
7157     }
7158   }
7159
7160   if (u1->info->var->defstate != u2->info->var->defstate) 
7161     {
7162       voptgenerror 
7163         (FLG_TYPE,
7164          message ("Function types are inconsistent. Parameter %d is "
7165                   "%s, but %s in assigned function: %s",
7166                   paramno, 
7167                   sstate_unparse (u1->info->var->defstate),
7168                   sstate_unparse (u2->info->var->defstate),
7169                   exprNode_unparse (e)),
7170          exprNode_loc (e));
7171     }
7172
7173   if (u1->info->var->nullstate != u2->info->var->nullstate) 
7174     {
7175       voptgenerror 
7176         (FLG_TYPE,
7177          message ("Function types are inconsistent. Parameter %d is "
7178                   "%s, but %s in assigned function: %s",
7179                   paramno, 
7180                   nstate_unparse (u1->info->var->nullstate),
7181                   nstate_unparse (u2->info->var->nullstate),
7182                   exprNode_unparse (e)),
7183          exprNode_loc (e));
7184     }
7185       
7186   if (sRef_getAliasKind (u1->sref) != sRef_getAliasKind (u2->sref))
7187     {
7188       voptgenerror 
7189         (FLG_TYPE,
7190          message ("Function types are inconsistent. Parameter %d is "
7191                   "%s, but %s in assigned function: %s",
7192                   paramno, 
7193                   alkind_unparse (sRef_getAliasKind (u1->sref)),
7194                   alkind_unparse (sRef_getAliasKind (u2->sref)),
7195                   exprNode_unparse (e)),
7196          exprNode_loc (e));
7197     }
7198
7199   if (sRef_getExKind (u1->sref) != sRef_getExKind (u2->sref))
7200     {
7201       voptgenerror 
7202         (FLG_TYPE,
7203          message ("Function types are inconsistent. Parameter %d is "
7204                   "%s, but %s in assigned function: %s",
7205                   paramno, 
7206                   exkind_unparse (sRef_getExKind (u1->sref)),
7207                   exkind_unparse (sRef_getExKind (u2->sref)),
7208                   exprNode_unparse (e)),
7209          exprNode_loc (e));
7210     }
7211 }
7212
7213 static void
7214 checkFunctionConformance (/*@unique@*/ /*@notnull@*/ uentry old,
7215                           /*@notnull@*/ uentry unew, 
7216                           bool mustConform, /*@unused@*/ bool completeConform)
7217 {
7218   uentryList oldParams  = uentry_getParams (old);
7219   uentryList newParams  = uentry_getParams (unew);
7220   ctype      newType    = unew->utype;
7221   ctype      oldType    = old->utype;
7222   ctype      oldRetType = ctype_unknown;
7223   ctype      newRetType = ctype_unknown;
7224
7225   if (uentry_isForward (old))
7226     {
7227       mustConform = FALSE;
7228       uentry_copyInto (old, unew);
7229       return;
7230     }
7231
7232   /*
7233   ** check return values
7234   */
7235   
7236   if (ctype_isKnown (oldType))
7237     {
7238       llassert (ctype_isFunction (oldType));
7239
7240       oldRetType = ctype_returnValue (oldType);
7241     }
7242
7243   if (ctype_isKnown (newType))
7244     {
7245       llassert (ctype_isFunction (newType));
7246
7247       newRetType = ctype_returnValue (newType);
7248     }
7249
7250   if (ctype_isKnown (oldRetType) && ctype_isKnown (newRetType)
7251       && !ctype_matchDef (newRetType, oldRetType))
7252     {
7253       if (mustConform) returnValueError (old, unew);
7254     }
7255   else 
7256     {
7257       if (ctype_isConj (newRetType))
7258         {
7259           if (ctype_isConj (oldRetType))
7260             {
7261               if (!ctype_sameAltTypes (newRetType, oldRetType))
7262                 {
7263                   if (optgenerror 
7264                       (FLG_INCONDEFS,
7265                        message ("Function %q inconsistently %rdeclared to "
7266                                 "return alternate types %s "
7267                                 "(types match, but alternates are not identical, "
7268                                 "so checking may not be correct)",
7269                                 uentry_getName (unew),
7270                                 uentry_isDeclared (old),
7271                                 ctype_unparse (newRetType)),
7272                        uentry_whereDeclared (unew)))
7273                     {
7274                       uentry_showWhereLastVal (old, ctype_unparse (oldRetType));
7275                     }
7276                 }
7277             }
7278           else
7279             {
7280               old->utype = ctype_makeFunction (oldRetType, uentryList_copy (newParams));
7281             }
7282         }
7283     }
7284
7285   uentry_checkStateConformance (old, unew, mustConform, completeConform);
7286
7287   if (!exitkind_equal (unew->info->fcn->exitCode, old->info->fcn->exitCode))
7288     {
7289       if (exitkind_isKnown (unew->info->fcn->exitCode))
7290         {
7291           if (optgenerror 
7292               (FLG_INCONDEFS,
7293                message ("Function %q inconsistently %rdeclared using %s",
7294                         uentry_getName (unew),
7295                         uentry_isDeclared (old),
7296                         exitkind_unparse (unew->info->fcn->exitCode)),
7297                uentry_whereDeclared (unew)))
7298             {
7299               uentry_showWhereSpecified (old);
7300             }
7301         }
7302       else
7303         {
7304           unew->info->fcn->exitCode = old->info->fcn->exitCode;
7305         }
7306     }
7307
7308   if (!qual_isUnknown (unew->info->fcn->nullPred))
7309     {
7310       if (!qual_equal (old->info->fcn->nullPred, unew->info->fcn->nullPred))
7311         {
7312           if (optgenerror
7313               (FLG_INCONDEFS,
7314                message ("Function %q inconsistently %rdeclared using %s",
7315                         uentry_getName (unew),
7316                         uentry_isDeclared (old),
7317                         qual_unparse (unew->info->fcn->nullPred)),
7318                uentry_whereDeclared (unew)))
7319             {
7320               uentry_showWhereSpecified (old);
7321             }
7322         }
7323     }
7324   else
7325     {
7326       unew->info->fcn->nullPred = old->info->fcn->nullPred;
7327     }
7328
7329   if (unew->info->fcn->specialCode != SPC_NONE)
7330     {
7331       if (old->info->fcn->specialCode != unew->info->fcn->specialCode)
7332         {
7333           if (optgenerror
7334               (FLG_INCONDEFS,
7335                message ("Function %q inconsistently %rdeclared using %s",
7336                         uentry_getName (unew),
7337                         uentry_isDeclared (old),
7338                         specCode_unparse (unew->info->fcn->specialCode)),
7339                uentry_whereDeclared (unew)))
7340             {
7341               uentry_showWhereSpecified (old);
7342             }
7343         }
7344     }
7345   else
7346     {
7347       unew->info->fcn->specialCode = old->info->fcn->specialCode;
7348     }
7349           
7350   /*
7351   ** check parameters
7352   */
7353   
7354   if (!uentryList_sameObject (oldParams, newParams)
7355       && (!uentryList_isMissingParams (oldParams)))
7356     {
7357       if (!uentryList_isMissingParams (newParams))
7358         {
7359           int paramno = 0;
7360           int nparams = uentryList_size (oldParams);
7361           bool checknames = context_maybeSet (FLG_DECLPARAMMATCH);
7362
7363           if (nparams != uentryList_size (newParams))
7364             {
7365               nargsError (old, unew);
7366             }
7367           
7368           if (uentryList_size (newParams) < nparams) 
7369             {
7370               nparams = uentryList_size (newParams);
7371             }
7372
7373           while (paramno < nparams)
7374             {
7375               uentry oldCurrent = uentryList_getN (oldParams, paramno);
7376               uentry newCurrent  = uentryList_getN (newParams, paramno);
7377               ctype  oldCurrentType = uentry_getType (oldCurrent);
7378               ctype  newCurrentType = uentry_getType (newCurrent);
7379
7380               llassert (uentry_isValid (oldCurrent)
7381                         && uentry_isValid (newCurrent));
7382               
7383               if (!uentry_isElipsisMarker (oldCurrent)
7384                   && !uentry_isElipsisMarker (newCurrent))
7385                 {
7386                   checkVarConformance (oldCurrent, newCurrent, 
7387                                        mustConform, completeConform);
7388                 }
7389
7390               if (checknames)
7391                 {
7392                   if (uentry_hasName (oldCurrent) 
7393                       && uentry_hasName (newCurrent))
7394                     {
7395                       cstring oldname = uentry_getName (oldCurrent);
7396                       cstring pfx = context_getString (FLG_DECLPARAMPREFIX);
7397                       cstring oname;
7398                       cstring nname = uentry_getName (newCurrent);
7399                       cstring nnamefix;
7400
7401                       if (cstring_isDefined (pfx)
7402                           && cstring_equalPrefix (oldname, cstring_toCharsSafe (pfx)))
7403                         {
7404                           oname = cstring_suffix (oldname, cstring_length (pfx));
7405                         }
7406                       else
7407                         {
7408                           oname = oldname;
7409                         /*@-branchstate@*/ } /*@=branchstate@*/
7410
7411                       if (cstring_isDefined (pfx)
7412                           && cstring_equalPrefix (nname, cstring_toCharsSafe (pfx)))
7413                         {
7414                           nnamefix = cstring_suffix (nname, cstring_length (pfx));
7415                         }
7416                       else
7417                         {
7418                           nnamefix = nname;
7419                         /*@-branchstate@*/ } /*@=branchstate@*/
7420
7421                       if (!cstring_equal (oname, nnamefix))
7422                         {
7423                           if (optgenerror
7424                               (FLG_DECLPARAMMATCH, 
7425                                message ("Definition parameter name %s does not match "
7426                                         "name of corresponding parameter in "
7427                                         "declaration: %s",
7428                                         nnamefix, oname),
7429                                uentry_whereLast (newCurrent)))
7430                             {
7431                               uentry_showWhereLastPlain (oldCurrent);
7432                             }
7433                         }
7434                       
7435                       cstring_free (oldname);
7436                       cstring_free (nname);
7437                     }
7438                 }
7439
7440               if (!ctype_match (oldCurrentType, newCurrentType))
7441                 {
7442                   paramTypeError (old, oldCurrent, oldCurrentType,
7443                                   unew, newCurrent, newCurrentType, paramno);
7444                 }
7445               else
7446                 {
7447                   if (ctype_isMissingParamsMarker (newCurrentType)
7448                       || ctype_isElips (newCurrentType)
7449                       || ctype_isMissingParamsMarker (oldCurrentType)
7450                       || ctype_isElips (oldCurrentType))
7451                     {
7452                       ;
7453                     }
7454                   else
7455                     {
7456                       if (ctype_isConj (newCurrentType))
7457                         {
7458                           if (ctype_isConj (oldCurrentType))
7459                             {
7460                               if (!ctype_sameAltTypes (newCurrentType, oldCurrentType))
7461                                 {
7462                                   if (optgenerror 
7463                                       (FLG_INCONDEFS,
7464                                        message ("Parameter %q inconsistently %rdeclared with "
7465                                                 "alternate types %s "
7466                                                 "(types match, but alternates are not identical, "
7467                                                 "so checking may not be correct)",
7468                                                 uentry_getName (newCurrent),
7469                                                 uentry_isDeclared (oldCurrent),
7470                                                 ctype_unparse (newCurrentType)),
7471                                        uentry_whereDeclared (unew)))
7472                                     {
7473                                       uentry_showWhereLastVal (oldCurrent,
7474                                                                ctype_unparse (oldCurrentType));
7475                                     }
7476                                 }
7477                             }
7478                           else
7479                             {
7480                               if (optgenerror 
7481                                   (FLG_INCONDEFS,
7482                                    message ("Parameter %q inconsistently %rdeclared with "
7483                                             "alternate types %s",
7484                                             uentry_getName (newCurrent),
7485                                             uentry_isDeclared (oldCurrent),
7486                                             ctype_unparse (newCurrentType)),
7487                                    uentry_whereDeclared (unew)))
7488                                 {
7489                                   uentry_showWhereLastVal (oldCurrent,
7490                                                            ctype_unparse (oldCurrentType));
7491                                   
7492                                 }
7493                             }
7494                         }
7495                       else 
7496                         {
7497                           if (ctype_isConj (oldCurrentType))
7498                             {
7499                               uentry_setType (newCurrent, oldCurrentType);
7500                             }
7501                         }
7502                     }
7503                 }
7504
7505               paramno++;  
7506               /*
7507                ** Forgot this!  detected by lclint:
7508                ** uentry.c:1257,15: Suspected infinite loop
7509                */
7510             }
7511         }
7512     }
7513
7514   if (!uentryList_isMissingParams (newParams))
7515     {
7516       if (ctype_isConj (oldRetType))
7517         {
7518           old->utype = ctype_makeFunction (oldRetType, 
7519                                            uentryList_copy (newParams));
7520         }
7521       else
7522         {
7523           old->utype = unew->utype;
7524         }
7525     }
7526
7527   checkGlobalsConformance (old, unew, mustConform, completeConform);
7528   checkModifiesConformance (old, unew, mustConform, completeConform);
7529
7530   if (specialClauses_isDefined (unew->info->fcn->specclauses))
7531     {
7532       if (!specialClauses_isDefined (old->info->fcn->specclauses))
7533         {
7534           if (optgenerror
7535               (FLG_INCONDEFS,
7536                message ("Function %q redeclared using special clauses (can only "
7537                         "be used in first declaration)",
7538                         uentry_getName (unew)),
7539                uentry_whereDeclared (unew)))
7540             {
7541               uentry_showWhereLast (old);
7542             }
7543         }
7544       else
7545         {
7546           specialClauses_checkEqual (old, unew);
7547         }
7548     }
7549
7550   if (fileloc_isUndefined (old->whereDeclared))
7551     {
7552       old->whereDeclared = fileloc_copy (unew->whereDeclared);
7553     }
7554   else if (fileloc_isUndefined (unew->whereDeclared))
7555     {
7556       unew->whereDeclared = fileloc_copy (old->whereDeclared);
7557     }
7558   else
7559     {
7560       /* no change */
7561     }
7562 }
7563
7564 void
7565 uentry_mergeConstantValue (uentry ue, /*@only@*/ multiVal m)
7566 {
7567   multiVal uval;
7568
7569   llassert (uentry_isValid (ue));
7570   llassert (uentry_isEitherConstant (ue));
7571
7572   uval = ue->info->uconst->val;
7573
7574   if (multiVal_isDefined (uval))
7575     {
7576       if (multiVal_isDefined (m))
7577         {
7578           if (!multiVal_equiv (uval, m))
7579             {
7580               if (optgenerror 
7581                   (FLG_INCONDEFS,
7582                    message ("%s %q defined with inconsistent value: %q",
7583                             ekind_capName (ue->ukind),
7584                             uentry_getName (ue), 
7585                             multiVal_unparse (m)),
7586                    g_currentloc))
7587                 {
7588                   uentry_showWhereLastExtra (ue, multiVal_unparse (uval));
7589                 }
7590             }
7591         }
7592       multiVal_free (m);
7593     }
7594   else
7595     {
7596       ue->info->uconst->val = m;
7597       multiVal_free (uval);
7598     }
7599 }
7600
7601 static
7602 bool checkTypeConformance (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew, 
7603                            bool mustConform)
7604 {
7605   bool typeError = FALSE;
7606
7607   if (uentry_isStructTag (old) || uentry_isUnionTag (old))
7608     {
7609       if (ctype_isSU (old->utype) && ctype_isSU (unew->utype))
7610         {
7611           if (mustConform)
7612             {
7613               checkStructConformance (old, unew); 
7614             }
7615         }
7616       else
7617         {
7618           if (!(ctype_isBogus (old->utype) || ctype_isBogus (unew->utype)))
7619             {
7620               llbug (message ("struct tags: bad types: %t / %t", 
7621                               old->utype, unew->utype));
7622             }
7623         }
7624     }
7625   else if (uentry_isEnumTag (old))
7626     {
7627       if (ctype_isEnum (old->utype) && ctype_isEnum (unew->utype))
7628         {
7629           if (mustConform) checkEnumConformance (old, unew);
7630         }
7631       else 
7632         {
7633           if (!(ctype_isBogus (old->utype) || ctype_isBogus (unew->utype)))
7634             {
7635               llbug (message ("enum! bad type: %s / %s", ctype_unparse (old->utype),
7636                               ctype_unparse (unew->utype)));
7637             }
7638         }
7639     }
7640   else if (!ctype_match (old->utype, unew->utype))
7641     {
7642       if (cstring_equal (uentry_rawName (old), context_getBoolName ()))
7643         {
7644           ctype realt = ctype_realType (unew->utype);
7645           
7646           if (ctype_isRealInt (realt) || ctype_isChar (realt))
7647             {
7648               unew->utype = ctype_bool;
7649             }
7650           else
7651             {
7652               if (mustConform)
7653                 {
7654                   typeError = optgenerror
7655                     (FLG_INCONDEFS,
7656                      message ("%q defined as %s", uentry_getName (old), 
7657                               ctype_unparse (realt)),
7658                      uentry_whereDeclared (unew));
7659                 }
7660             }
7661         } 
7662       else 
7663         {
7664           if (mustConform)
7665             {
7666               ctype oldr = ctype_realType (old->utype);
7667               ctype newr = ctype_realType (unew->utype);
7668               
7669               if (ctype_isStruct (oldr) && ctype_isStruct (newr))
7670                 {
7671                   checkStructConformance (old, unew);
7672                 }
7673               else if (ctype_isUnion (oldr) && ctype_isUnion (newr))
7674                 {
7675                   checkStructConformance (old, unew);
7676                 }
7677               else if (ctype_isEnum (oldr) && ctype_isEnum (newr))
7678                 {
7679                   checkEnumConformance (old, unew);
7680                 }
7681               else if (uentry_isConstant (old) 
7682                        && (ctype_isAbstract (oldr) && ctype_isEnum (newr)))
7683                 {
7684                   /* okay...for now! (should check the type is reset later... */
7685                 }
7686               else
7687                 {
7688                   DPRINTF (("YABA!"));
7689                   if (optgenerror 
7690                       (FLG_INCONDEFS,
7691                        message ("%s %q %rdeclared with inconsistent type: %t",
7692                                 ekind_capName (unew->ukind),
7693                                 uentry_getName (unew), 
7694                                 uentry_isDeclared (old),
7695                                 unew->utype),
7696                        uentry_whereDeclared (unew)))
7697                     {
7698                       uentry_showWhereLast (old);
7699                       typeError = TRUE;
7700                     }
7701                 }
7702             }
7703         }
7704     }
7705   else
7706     {
7707       /* no error */
7708     }
7709
7710   return typeError;
7711 }
7712
7713 static void
7714 uentry_checkDatatypeConformance (/*@notnull@*/ uentry old,
7715                                  /*@notnull@*/ uentry unew,
7716                                  bool mustConform, bool completeConform)
7717 {
7718   if (ctype_isDefined (unew->info->datatype->type))
7719     {
7720       /*
7721       ** bool is hard coded here, since it is built into LCL.
7722       ** For now, we're stuck with LCL's types.
7723       */
7724
7725       if (ctype_isDirectBool (old->utype) &&
7726           cstring_equalLit (unew->uname, "bool"))
7727         {
7728           /* if (!context_getFlag (FLG_ABSTRACTBOOL))
7729              evs 2000-07-25: removed
7730           */
7731               unew->utype = ctype_bool;
7732         }
7733       
7734       if (ctype_isUnknown (old->info->datatype->type))
7735         {
7736           old->info->datatype->type = unew->info->datatype->type;
7737         }
7738       else
7739         {
7740           DPRINTF (("Old: %s / New: %s",
7741                     uentry_unparseFull (old),
7742                     uentry_unparseFull (unew)));
7743           DPRINTF (("Types: %s / %s",
7744                     ctype_unparse (old->info->datatype->type),
7745                     ctype_unparse (unew->info->datatype->type)));
7746
7747           if (ctype_matchDef (old->info->datatype->type,
7748                               unew->info->datatype->type))
7749             {
7750               ;
7751             }
7752           else
7753             {
7754               if (optgenerror 
7755                   (FLG_INCONDEFS,
7756                    message
7757                    ("Type %q %s with inconsistent type: %t",
7758                     uentry_getName (unew), 
7759                     uentry_reDefDecl (old, unew),
7760                     unew->info->datatype->type),
7761                    uentry_whereDeclared (unew)))
7762                 {
7763                   uentry_showWhereLastExtra 
7764                     (old, cstring_copy (ctype_unparse (old->info->datatype->type)));
7765                 }
7766
7767               old->info->datatype->type = unew->info->datatype->type;
7768             }
7769         }
7770     }
7771   
7772   if (unew->info->datatype->abs != MAYBE)
7773     {
7774       if (ynm_isOff (old->info->datatype->abs)
7775           && ynm_isOn (unew->info->datatype->abs))
7776         {
7777           if (!ctype_isDirectBool (old->utype))
7778             {
7779               if (optgenerror 
7780                   (FLG_INCONDEFS,
7781                    message 
7782                    ("Datatype %q inconsistently %rdeclared as abstract type",
7783                     uentry_getName (unew), 
7784                     uentry_isDeclared (old)),
7785                    uentry_whereDeclared (unew)))
7786                 {
7787                   uentry_showWhereLastPlain (old);
7788                 }
7789             }
7790         }
7791       else if (ynm_isOn (old->info->datatype->abs)
7792                && ynm_isOff (unew->info->datatype->abs))
7793         {
7794           if (!ctype_isDirectBool (old->utype))
7795             {
7796               if (optgenerror 
7797                   (FLG_INCONDEFS,
7798                    message 
7799                    ("Datatype %q inconsistently %rdeclared as concrete type",
7800                     uentry_getName (unew), 
7801                     uentry_isDeclared (old)),
7802                    uentry_whereDeclared (unew)))
7803                 {
7804                   uentry_showWhereLastPlain (old);
7805                 }
7806             }
7807         }
7808       else
7809         {
7810           ;
7811         }
7812     }
7813   else 
7814     {
7815       if (ynm_isOn (old->info->datatype->abs))
7816         {
7817           old->sref = unew->sref;
7818           unew->info->datatype->mut = old->info->datatype->mut;
7819           
7820           if (completeConform
7821               && uentry_isReallySpecified (old))
7822             {
7823               if (optgenerror 
7824                   (FLG_NEEDSPEC,
7825                    message 
7826                    ("Datatype %q specified as abstract, "
7827                     "but abstract annotation not used in declaration",
7828                     uentry_getName (unew)), 
7829                    uentry_whereDeclared (unew)))
7830                 {
7831                   uentry_showWhereLastPlain (old);
7832                 }
7833             }
7834         }
7835     }
7836   
7837   unew->info->datatype->abs = old->info->datatype->abs;   
7838   
7839   if (ynm_isMaybe (unew->info->datatype->mut))
7840     {
7841       if (completeConform && ynm_isOff (old->info->datatype->mut)
7842           && uentry_isReallySpecified (old))
7843         {
7844           if (optgenerror 
7845               (FLG_NEEDSPEC,
7846                message 
7847                ("Datatype %q specified as immutable, "
7848                 "but immutable annotation not used in declaration",
7849                 uentry_getName (unew)), 
7850                uentry_whereDeclared (unew)))
7851             {
7852               uentry_showWhereLastPlain (old);
7853             }
7854         }
7855       
7856       unew->info->datatype->mut = old->info->datatype->mut;
7857     }
7858   else if (ynm_isMaybe (old->info->datatype->mut))
7859     {
7860       old->info->datatype->mut = unew->info->datatype->mut;
7861     }
7862   else
7863     {
7864       if (ynm_isOn (old->info->datatype->abs))
7865         {
7866           if (ynm_isOn (old->info->datatype->mut) && ynm_isOff (unew->info->datatype->mut))
7867             {
7868               if (optgenerror
7869                   (FLG_INCONDEFS,
7870                    message ("Datatype %q inconsistently %rdeclared as immutable",
7871                             uentry_getName (unew), 
7872                             uentry_isDeclared (old)),
7873                    uentry_whereDeclared (unew)))
7874                 {
7875                   uentry_showWhereLastPlain (old);
7876                 }
7877             }
7878           else 
7879             {
7880               if (ynm_isOff (old->info->datatype->mut)
7881                   && ynm_isOn (unew->info->datatype->mut))
7882                 {
7883                   if (optgenerror
7884                       (FLG_INCONDEFS,
7885                        message ("Datatype %q inconsistently %rdeclared as mutable",
7886                                 uentry_getName (unew), 
7887                                 uentry_isDeclared (old)),
7888                        uentry_whereDeclared (unew)))
7889                     {
7890                       uentry_showWhereLastPlain (old);
7891                     }
7892                 }
7893             }
7894         }
7895       old->info->datatype->mut = unew->info->datatype->mut;       
7896     }
7897
7898   uentry_checkStateConformance (old, unew, mustConform, completeConform);
7899 }
7900
7901 static void
7902 uentry_checkConstantConformance (/*@notnull@*/ uentry old,
7903                                  /*@notnull@*/ uentry unew,
7904                                  bool mustConform, 
7905                                  /*@unused@*/ bool completeConform)
7906 {
7907   multiVal oldVal = old->info->uconst->val;
7908   multiVal newVal = unew->info->uconst->val;
7909   
7910   if (multiVal_isDefined (oldVal))
7911     {
7912       if (multiVal_isDefined (newVal))
7913         {
7914           if (!multiVal_equiv (oldVal, newVal))
7915             {
7916               if (mustConform
7917                   && optgenerror 
7918                   (FLG_INCONDEFS,
7919                    message ("%s %q %rdeclared with inconsistent value: %q",
7920                             ekind_capName (unew->ukind),
7921                             uentry_getName (unew), 
7922                             uentry_isDeclared (old),
7923                             multiVal_unparse (newVal)),
7924                    uentry_whereDeclared (unew)))
7925                 {
7926                   uentry_showWhereLastExtra (old, multiVal_unparse (oldVal));
7927                 }
7928             }
7929           
7930           unew->info->uconst->val = multiVal_copy (oldVal);
7931           multiVal_free (newVal);
7932         }
7933       else
7934         {
7935           ;
7936         }
7937     }
7938   else
7939     {
7940       old->info->uconst->val = multiVal_copy (newVal);
7941     }
7942 }
7943
7944 static void 
7945 uentry_checkConformance (/*@unique@*/ /*@notnull@*/ uentry old, 
7946                          /*@notnull@*/ uentry unew, bool mustConform,
7947                          bool completeConform)
7948 {
7949   bool typeError = FALSE;
7950   bool fcnConformance = FALSE;
7951
7952   if (!ekind_equal (unew->ukind, old->ukind))
7953     {
7954       /*
7955       ** okay, only if one is a function and the other is
7956       ** a variable of type function.
7957       */
7958
7959       if (unew->ukind == KENUMCONST
7960           && old->ukind == KCONST)
7961         {
7962           old->ukind = KENUMCONST;
7963           goto nokinderror;
7964         }
7965
7966       if (unew->ukind == KFCN 
7967           && old->ukind == KCONST
7968           && ctype_isUnknown (old->utype))
7969         {
7970           /*
7971           ** When a function is defined with an unparam macro
7972           */
7973
7974           uentry_copyInto (old, unew);
7975           return;
7976         }
7977
7978       if (uentry_isExpandedMacro (old) 
7979           && uentry_isEitherConstant (unew))
7980         {
7981           uentry_copyInto (old, unew);
7982           return;
7983         }
7984
7985       if (uentry_isEndIter (unew))
7986         {
7987           if (ctype_isUnknown (old->utype))
7988             {
7989               if (!uentry_isSpecified (old)
7990                   && uentry_isCodeDefined (unew))
7991                 {
7992                   if (!fileloc_withinLines (uentry_whereDefined (old),
7993                                             uentry_whereDeclared (unew), 2))
7994                     { /* bogus!  will give errors if there is too much whitespace */
7995                       voptgenerror
7996                         (FLG_SYNTAX,
7997                          message
7998                          ("Iterator finalized name %q does not match name in "
7999                           "previous iter declaration (should be end_%q).  This iter "
8000                           "is declared at %q", 
8001                           uentry_getName (unew),
8002                           uentry_getName (old),
8003                           fileloc_unparse (uentry_whereDefined (old))),
8004                          uentry_whereDeclared (old));
8005                     }
8006                 }
8007
8008               uentry_copyInto (old, unew);
8009               return;
8010             }
8011           else
8012             {
8013               KindConformanceError (old, unew, mustConform);
8014             }
8015         }
8016
8017       if (uentry_isFunction (unew))
8018         {
8019           if (uentry_isVariable (old))
8020             {
8021               if (!ctype_isUnknown (old->utype))
8022                 {
8023                   if (ctype_isFunction (old->utype))
8024                     {
8025                       uentry_makeVarFunction (old);
8026                       checkFunctionConformance (old, unew, mustConform,
8027                                                 completeConform);
8028                       fcnConformance = TRUE;
8029                     }
8030                   else
8031                     {
8032                       KindConformanceError (old, unew, mustConform);
8033                     }
8034                 }
8035               else
8036                 {
8037                   if (uentry_isExpandedMacro (old))
8038                     {
8039                       if (fileloc_isUndefined (unew->whereDefined))
8040                         {
8041                           unew->whereDefined = fileloc_update (unew->whereDefined, 
8042                                                               old->whereDefined);
8043                         }
8044
8045                       uentry_copyInto (old, unew);
8046                       old->used = unew->used = TRUE;
8047                       return;
8048                     }
8049                   else
8050                     {
8051                       /* undeclared identifier */
8052                       old->utype = unew->utype;
8053                       uentry_makeVarFunction (old);
8054                       checkFunctionConformance (old, unew, FALSE, FALSE);
8055                       fcnConformance = TRUE;
8056                     }
8057                 }
8058             }
8059           else
8060             {
8061               KindConformanceError (old, unew, mustConform);
8062             }
8063         }
8064       else if (uentry_isFunction (old) && uentry_isVariable (unew))
8065         {
8066           if (!ctype_isUnknown (unew->utype))
8067             {
8068               if (ctype_isFunction (unew->utype))
8069                 {
8070                   uentry_makeVarFunction (unew);
8071                   checkFunctionConformance (old, unew, mustConform, completeConform);
8072                   fcnConformance = TRUE;
8073                 }
8074               else
8075                 {
8076                   KindConformanceError (old, unew, mustConform);
8077                 }
8078             }
8079           else
8080             {
8081               KindConformanceError (old, unew, mustConform);
8082             }
8083         }
8084       else
8085         {
8086           KindConformanceError (old, unew, mustConform);
8087         }
8088     }
8089   else
8090     {
8091       /*
8092       ** check parameter lists for functions 
8093       ** (before type errors, to get better messages
8094       */
8095
8096       if (uentry_isFunction (old))
8097         {
8098           checkFunctionConformance (old, unew, mustConform, completeConform);
8099           fcnConformance = TRUE;
8100         }
8101       else 
8102         {
8103           if (!ctype_isUndefined (old->utype))
8104             {
8105               typeError = checkTypeConformance (old, unew, mustConform);
8106             }
8107         }
8108     }
8109
8110  nokinderror:
8111
8112   if (uentry_isEitherConstant (old) && uentry_isEitherConstant (unew))
8113     {
8114       uentry_checkConstantConformance (old, unew, mustConform, completeConform);
8115     }
8116
8117   if (uentry_isDatatype (old) && uentry_isDatatype (unew))
8118     {
8119       DPRINTF (("Check datatype: %s / %s",
8120                 uentry_unparseFull (old),
8121                 uentry_unparseFull (unew)));
8122
8123       uentry_checkDatatypeConformance (old, unew, mustConform, completeConform);
8124     }
8125
8126   if (uentry_isVariable (old) && uentry_isVariable (unew))
8127     {
8128       if (!typeError && 
8129           !ctype_matchDef (old->utype, unew->utype))
8130         {
8131           if (optgenerror 
8132               (FLG_INCONDEFS,
8133                message
8134                ("Variable %q %s with inconsistent type (arrays and pointers are "
8135                 "not identical in variable declarations): %t",
8136                 uentry_getName (unew), 
8137                 uentry_reDefDecl (old, unew),
8138                 unew->utype),
8139                uentry_whereDeclared (unew)))
8140             {
8141               uentry_showWhereLast (old);
8142               
8143               /*
8144               ** Avoid repeated errors.
8145               */
8146
8147               if (uentry_isCodeDefined (old) && uentry_isCodeDefined (unew))
8148                 {
8149                   old->whereDefined = fileloc_update (old->whereDefined,
8150                                                       fileloc_undefined);
8151                 }
8152
8153               typeError = TRUE;
8154             }
8155         }
8156
8157       checkVarConformance (old, unew, mustConform, completeConform);
8158     }
8159
8160   if (fcnConformance)
8161     {
8162       /* old->utype = unew->utype; */
8163     }
8164   else
8165     {
8166       if (ctype_isConj (old->utype))
8167         {
8168           if (ctype_isConj (unew->utype))
8169             {
8170               if (!ctype_sameAltTypes (old->utype, unew->utype))
8171                 {
8172                   if (optgenerror 
8173                       (FLG_INCONDEFS,
8174                        message ("%s %q inconsistently %rdeclared with "
8175                                 "alternate types %s "
8176                                 "(types match, but alternates are not identical, "
8177                                 "so checking may not be correct)",
8178                                 ekind_capName (uentry_getKind (old)),
8179                                 uentry_getName (unew),
8180                                 uentry_isDeclared (old),
8181                                 ctype_unparse (unew->utype)),
8182                        uentry_whereDeclared (unew)))
8183                     {
8184                       uentry_showWhereLastVal (old, ctype_unparse (old->utype));
8185                     }
8186                   else
8187                     {
8188                       old->utype = unew->utype;
8189                     }
8190                 }
8191             }
8192         }
8193       else
8194         {
8195           if (ctype_isUnknown (old->utype))
8196             {
8197               old->utype = unew->utype;
8198             }
8199         }
8200     }  
8201
8202   if (unew->ukind == old->ukind) 
8203     {
8204       sfree (unew->info);
8205       unew->info = uinfo_copy (old->info, old->ukind);
8206     }
8207
8208   sRef_storeState (old->sref);
8209   sRef_storeState (unew->sref);
8210 }
8211
8212 /*
8213 ** modifies spec to reflect def, reports any inconsistencies
8214 */
8215
8216 void
8217 uentry_mergeEntries (uentry spec, /*@only@*/ uentry def)
8218 {
8219   llassert (uentry_isValid (spec));
8220   llassert (uentry_isValid (def));
8221   llassert (cstring_equal (spec->uname, def->uname));
8222
8223   uentry_checkConformance (spec, def, TRUE, 
8224                            context_getFlag (FLG_NEEDSPEC));
8225
8226   /* was: !(fileloc_isImport (uentry_whereSpecified (spec)))); */
8227
8228   /*
8229   ** okay, declarations conform.  Propagate extra information.
8230   */
8231
8232   uentry_setDefined (spec, uentry_whereDefined (def));
8233   uentry_setDeclared (spec, uentry_whereDeclared (def));
8234
8235   if (uentry_isStatic (def))
8236     {
8237       if (optgenerror 
8238           (FLG_INCONDEFS,
8239            message ("%s %q specified, but declared as static",
8240                     ekind_capName (def->ukind),
8241                     uentry_getName (def)),
8242            uentry_whereDeclared (def)))
8243         {
8244           uentry_showWhereSpecified (spec);
8245         }
8246     }
8247   else 
8248     {
8249       spec->storageclass = def->storageclass;
8250     }
8251
8252   sRef_storeState (spec->sref);
8253
8254   spec->used = def->used || spec->used;
8255   spec->hasNameError |= def->hasNameError;
8256
8257   uentry_free (def);
8258
8259   if (!spec->hasNameError)
8260     {
8261       uentry_checkName (spec);
8262     }
8263   else
8264     {
8265       ;
8266     }
8267 }
8268
8269 /*
8270 ** Can't generate function redeclaration errors when the 
8271 ** entries are merged, since we don't yet know if its the
8272 ** definition of the function.
8273 */
8274
8275 void
8276 uentry_clearDecl (void)
8277 {
8278   posRedeclared = uentry_undefined;
8279   fileloc_free (posLoc);
8280   posLoc = fileloc_undefined;
8281 }
8282
8283 void
8284 uentry_checkDecl (void)
8285 {
8286   if (uentry_isValid (posRedeclared))
8287     {
8288       llassert (fileloc_isDefined (posLoc));
8289
8290       if (uentry_isCodeDefined (posRedeclared))
8291         {
8292           if (optgenerror (FLG_REDECL,
8293                            message ("%s %q declared after definition", 
8294                                     ekind_capName (posRedeclared->ukind),
8295                                     uentry_getName (posRedeclared)),
8296                            posLoc))
8297             {
8298               llgenindentmsg (message ("Definition of %q", 
8299                                        uentry_getName (posRedeclared)),
8300                               posRedeclared->whereDeclared);
8301             }
8302         }
8303       else
8304         {
8305           if (optgenerror (FLG_REDECL,
8306                            message ("%s %q declared more than once", 
8307                                     ekind_capName (posRedeclared->ukind),
8308                                     uentry_getName (posRedeclared)),
8309                            posLoc))
8310             {
8311               llgenindentmsg (message ("Previous declaration of %q", 
8312                                        uentry_getName (posRedeclared)),
8313                               posRedeclared->whereDeclared);
8314             }
8315         }
8316     }
8317
8318   fileloc_free (posLoc);
8319   posLoc = fileloc_undefined;
8320   posRedeclared = uentry_undefined;
8321 }
8322
8323 /*
8324 ** Redefinition of old as unew.
8325 ** modifies old to reflect unew, reports any inconsistencies
8326 */
8327
8328 void
8329 uentry_mergeDefinition (uentry old, /*@only@*/ uentry unew)
8330 {
8331   fileloc olddef = uentry_whereDeclared (old);
8332   fileloc unewdef = uentry_whereDeclared (unew);
8333   bool mustConform;
8334   bool wasForward;
8335  
8336   if (uentry_isExtern (unew))
8337     {
8338       uentry_setUsed (old, unewdef);
8339     }
8340
8341   wasForward = 
8342     fileloc_isUndefined (olddef) 
8343       && fileloc_isDefined (uentry_whereDefined (old)) 
8344         && !uentry_isExpandedMacro (old);
8345   
8346   if (!context_getFlag (FLG_INCONDEFSLIB)
8347       && (fileloc_isLib (olddef) || fileloc_isImport (olddef)))
8348     {
8349       mustConform = FALSE;
8350     }
8351   else
8352     {
8353       mustConform = TRUE;
8354     }
8355   
8356   llassert (uentry_isValid (old));
8357   llassert (uentry_isValid (unew));
8358   llassert (cstring_equal (old->uname, unew->uname));
8359
8360   /*
8361   ** should check old one was extern!
8362   */
8363
8364   if (uentry_isStatic (old))
8365     {
8366       if (!(uentry_isStatic (unew)))
8367         {
8368           if (optgenerror 
8369               (FLG_SHADOW,
8370                message ("%s %q shadows static declaration",
8371                         ekind_capName (unew->ukind),
8372                         uentry_getName (unew)),
8373                unewdef))
8374             {
8375               uentry_showWhereLast (old);
8376             }
8377         }
8378       else
8379         {
8380           uentry_setDeclDef (old, unewdef);
8381         }
8382     }
8383   else if (uentry_isStatic (unew))
8384     {
8385       uentry_setDeclDef (old, unewdef);
8386     }
8387   else if (uentry_isExtern (old))
8388     {
8389       uentry_setDeclared (old, unewdef);
8390     }
8391   else
8392     {
8393       if (!uentry_isExtern (unew) && !uentry_isForward (old)
8394           && !fileloc_equal (olddef, unewdef)
8395           && !fileloc_isUndefined (olddef)
8396           && !fileloc_isUndefined (unewdef)
8397           && !fileloc_isBuiltin (olddef)
8398           && !fileloc_isBuiltin (unewdef)
8399           && !uentry_isYield (old)
8400           && !(fileloc_isLib (olddef) || fileloc_isImport (olddef)))
8401         {
8402           if (uentry_isVariable (old) || uentry_isVariable (unew))
8403             {
8404               ; /* will report redeclaration error later */
8405             }
8406           else
8407             {
8408               if (fileloc_isDefined (uentry_whereDefined (old)))
8409                 {
8410                   if (optgenerror
8411                       (FLG_REDEF,
8412                        message ("%s %q defined more than once", 
8413                                 ekind_capName (unew->ukind),
8414                                 uentry_getName (unew)),
8415                        uentry_whereLast (unew)))
8416                     {
8417                       llgenindentmsg
8418                         (message ("Previous definition of %q", 
8419                                   uentry_getName (old)),
8420                          uentry_whereLast (old));
8421                     }
8422                   /*
8423                   if (uentry_isDatatype (old) || uentry_isAnyTag (old))
8424                     {
8425                       uentry_copyInto (old, unew);
8426                       old->sref = sRef_saveCopy (old->sref);
8427                     }
8428                     */
8429                 }
8430             }
8431         }
8432       else
8433         {
8434           if (fileloc_isLib (olddef)
8435               || fileloc_isUndefined (olddef)
8436               || fileloc_isImport (olddef))
8437             {
8438               if (uentry_isExtern (unew)) 
8439                 {
8440                   if (uentry_isExtern (old)
8441                       || (fileloc_isDefined (uentry_whereDeclared (old))
8442                           && (!fileloc_equal (uentry_whereDeclared (old),
8443                                               uentry_whereDefined (old)))))
8444                     {
8445                       if (optgenerror
8446                           (FLG_REDECL,
8447                            message ("%s %q declared more than once", 
8448                                     ekind_capName (unew->ukind),
8449                                     uentry_getName (unew)),
8450                            unew->whereDeclared))
8451                         {
8452                           llgenindentmsg
8453                             (message ("Previous declaration of %q", 
8454                                       uentry_getName (old)),
8455                              old->whereDeclared);
8456                         }
8457                     }
8458                   
8459                   uentry_setExtern (old);
8460                 }
8461               else
8462                 {
8463                   uentry_setDefined (old, unewdef);
8464                 }
8465             }
8466         }
8467     }
8468
8469   uentry_checkConformance (old, unew, mustConform, FALSE);
8470
8471   old->used = old->used || unew->used;
8472   old->uses = filelocList_append (old->uses, unew->uses);
8473   unew->uses = filelocList_undefined; 
8474
8475   sRef_storeState (old->sref); 
8476   sRef_storeState (unew->sref);
8477
8478   if (wasForward)
8479     {
8480       old->whereDefined = fileloc_update (old->whereDefined,
8481                                           fileloc_undefined);
8482     }
8483
8484   /*
8485   ** No redeclaration errors for functions here, since we
8486   ** don't know if this is the definition of the function.
8487   */
8488
8489   if (fileloc_isUser (old->whereDeclared)
8490       && fileloc_isUser (unew->whereDeclared)
8491       && !fileloc_equal (old->whereDeclared, unew->whereDeclared)
8492       && !fileloc_isDefined (unew->whereDefined))
8493     {
8494       if (uentry_isFunction (old))
8495         {
8496           /*@-temptrans@*/ posRedeclared = old; /*@=temptrans@*/
8497           posLoc = fileloc_update (posLoc, unew->whereDeclared);
8498         }
8499       else
8500         {
8501           if (optgenerror (FLG_REDECL,
8502                            message ("%s %q declared more than once", 
8503                                     ekind_capName (unew->ukind),
8504                                     uentry_getName (unew)),
8505                            unew->whereDeclared))
8506             {
8507               llgenindentmsg (message ("Previous declaration of %q", 
8508                                        uentry_getName (old)),
8509                               old->whereDeclared);
8510             }
8511         }
8512     }
8513
8514   if (fileloc_isUndefined (old->whereDefined))
8515     {
8516       old->whereDefined = fileloc_update (old->whereDefined, unew->whereDefined);
8517     }
8518   else
8519     {
8520       if (!context_processingMacros ()
8521           && fileloc_isUser (old->whereDefined) 
8522           && fileloc_isUser (unew->whereDefined)
8523           && !fileloc_equal (old->whereDefined, unew->whereDefined))
8524         {
8525           if (uentry_isVariable (unew) || uentry_isFunction (unew))
8526             {
8527               if (uentry_isVariable (unew) 
8528                   && uentry_isExtern (unew))
8529                 {
8530                   if (optgenerror (FLG_REDECL,
8531                                    message ("%s %q declared after definition", 
8532                                             ekind_capName (unew->ukind),
8533                                             uentry_getName (unew)),
8534                                    unew->whereDeclared))
8535                     {
8536                       llgenindentmsg (message ("Definition of %q", 
8537                                                uentry_getName (old)),
8538                                       old->whereDefined);
8539                     }
8540                 }
8541               else
8542                 {
8543                   if (optgenerror (FLG_REDEF,
8544                                    message ("%s %q redefined", 
8545                                             ekind_capName (unew->ukind),
8546                                             uentry_getName (unew)),
8547                                    unew->whereDefined))
8548                     {
8549                       llgenindentmsg (message ("Previous definition of %q", 
8550                                                uentry_getName (old)),
8551                                       old->whereDefined);
8552                     }
8553                 }
8554             }
8555         }
8556     }
8557
8558   if (uentry_isExternal (unew))
8559     {
8560       old->whereDefined = fileloc_createExternal ();
8561     }
8562
8563   if (unew->hasNameError)
8564     {
8565       old->hasNameError = TRUE;
8566     }
8567
8568   uentry_free (unew);
8569
8570   if (!old->hasNameError)
8571     {
8572       uentry_checkName (old);
8573     }
8574
8575   llassert (!ctype_isUndefined (old->utype));
8576 }
8577
8578 void
8579 uentry_copyState (uentry res, uentry other)
8580 {
8581   llassert (uentry_isValid (res));
8582   llassert (uentry_isValid (other));
8583
8584   res->used = other->used;
8585
8586   res->info->var->kind = other->info->var->kind;
8587   res->info->var->defstate = other->info->var->defstate;
8588   res->info->var->nullstate = other->info->var->nullstate;
8589   res->info->var->checked = other->info->var->checked;
8590
8591   sRef_copyState (res->sref, other->sref);
8592 }
8593
8594 bool
8595 uentry_sameKind (uentry u1, uentry u2)
8596 {
8597   if (uentry_isValid (u1) && uentry_isValid (u2))
8598     {
8599       if (uentry_isVar (u1) && uentry_isVar (u2))
8600         {
8601           ctype c1 = u1->utype;
8602           ctype c2 = u2->utype;
8603
8604           if (ctype_isUnknown (c1) || ctype_isUnknown (c2)) return FALSE;
8605
8606           /*
8607           ** both functions, or both not functions
8608           */
8609
8610           return (bool_equal (ctype_isFunction (c1), ctype_isFunction (c2)));
8611         }
8612       else
8613         {
8614           return ((u1->ukind == u2->ukind));
8615         }
8616     }
8617   
8618   return FALSE;
8619 }
8620    
8621 static void uentry_copyInto (/*@unique@*/ uentry unew, uentry old)
8622 {
8623   llassert (uentry_isValid (unew));
8624   llassert (uentry_isValid (old));
8625
8626   unew->ukind = old->ukind;
8627   unew->uname = cstring_copy (old->uname);
8628   unew->utype = old->utype;
8629
8630   unew->whereSpecified = fileloc_copy (old->whereSpecified);
8631   unew->whereDefined = fileloc_copy (old->whereDefined);
8632   unew->whereDeclared = fileloc_copy (old->whereDeclared);
8633
8634   unew->sref = sRef_saveCopy (old->sref); /* Memory leak! */
8635   unew->used = old->used;
8636   unew->lset = FALSE;
8637   unew->isPrivate = old->isPrivate;
8638   unew->hasNameError = old->hasNameError;
8639   unew->uses = filelocList_undefined;
8640
8641   unew->storageclass = old->storageclass;
8642   unew->info = uinfo_copy (old->info, old->ukind);
8643 }
8644
8645
8646 uentry
8647 uentry_copy (uentry e)
8648 {
8649   if (uentry_isValid (e))
8650     {
8651       uentry enew = uentry_alloc ();
8652       DPRINTF (("copy: %s", uentry_unparseFull (e)));
8653       uentry_copyInto (enew, e);
8654       DPRINTF (("Here we are..."));
8655       DPRINTF (("original: %s", uentry_unparseFull (e)));
8656       DPRINTF (("copy: %s", uentry_unparse (enew)));
8657       DPRINTF (("copy: %s", uentry_unparseFull (enew)));
8658       return enew;
8659     }
8660   else
8661     {
8662       return uentry_undefined;
8663     }
8664 }
8665
8666 void
8667 uentry_setState (uentry res, uentry other)
8668 {
8669   llassert (uentry_isValid (res));
8670   llassert (uentry_isValid (other));
8671
8672   llassert (res->ukind == other->ukind);
8673   llassert (res->ukind == KVAR);
8674
8675   res->sref = sRef_saveCopy (other->sref);
8676   res->used = other->used;
8677   filelocList_free (res->uses); 
8678   res->uses = other->uses; 
8679   other->uses = filelocList_undefined; 
8680   res->lset = other->lset;
8681 }
8682
8683 void
8684 uentry_mergeUses (uentry res, uentry other)
8685 {
8686   llassert (uentry_isValid (res));
8687   llassert (uentry_isValid (other));
8688
8689   res->used = other->used || res->used;
8690   res->lset = other->lset || res->lset;
8691   res->uses = filelocList_append (res->uses, other->uses);
8692   other->uses = filelocList_undefined;
8693 }
8694
8695
8696 /*
8697 ** This is a really ugly routine.
8698 **
8699 ** gack...fix this one day.
8700 */
8701
8702 /*
8703 ** flip == TRUE
8704 **   >> res is the false branch, other is the true branch (or continuation)
8705 ** flip == FALSE
8706 **   >> res is the true branch, other is the false branch (or continutation)
8707 **
8708 ** opt == TRUE if,
8709 **
8710 ** <other>
8711 ** if <res> ;
8712 **
8713 ** References not effected by res are propagated from other.
8714 */
8715
8716 static void
8717   branchStateError (/*@notnull@*/ uentry res, /*@notnull@*/ uentry other, 
8718                     bool flip, clause cl, fileloc loc)
8719 {
8720   if (optgenerror 
8721       (FLG_BRANCHSTATE,
8722        message ("%s %q is %s %s, but %s %s.",
8723                 ekind_capName (res->ukind), uentry_getName (res),
8724                 sRef_stateVerb (res->sref), clause_nameFlip (cl, flip),
8725                 sRef_stateAltVerb (res->sref), clause_nameFlip (cl, !flip)),
8726        loc))
8727     {
8728       if (sRef_isDead (res->sref))
8729         {
8730           sRef_showStateInfo (res->sref);
8731         }
8732       else if (sRef_isKept (res->sref))
8733         {
8734           sRef_showAliasInfo (res->sref);
8735         }
8736       else /* dependent */
8737         {
8738           sRef_showAliasInfo (res->sref);
8739           sRef_showAliasInfo (other->sref);
8740         }
8741       
8742       sRef_setAliasKind (res->sref, AK_ERROR, fileloc_undefined);
8743     }
8744 }
8745
8746 static bool incompatibleStates (sRef rs, sRef os)
8747 {
8748   alkind rk = sRef_getAliasKind (rs);
8749   alkind ok = sRef_getAliasKind (os);
8750
8751   if (alkind_isError (rk) || alkind_isError (ok))
8752     {
8753       return FALSE;
8754     }
8755   else
8756     {
8757       return ((sRef_isDead (rs)
8758                || (alkind_isKept (rk) && !alkind_isKept (ok))
8759                || (alkind_isDependent (rk) 
8760                    && !alkind_isDependent (ok) && !alkind_isTemp (ok)))
8761               && (sRef_isAllocated (os) || sRef_isStateDefined (os)));
8762     }
8763 }
8764
8765 static void
8766   branchStateAltError (/*@notnull@*/ uentry res,
8767                        /*@notnull@*/ uentry other, bool flip,
8768                        clause cl, fileloc loc)
8769 {
8770   if (optgenerror 
8771       (FLG_BRANCHSTATE,
8772        message ("%s %q is %s %s, but %s %s.",
8773                 ekind_capName (res->ukind), uentry_getName (res),
8774                 sRef_stateVerb (other->sref), clause_nameFlip (cl, flip),
8775                 sRef_stateAltVerb (other->sref), clause_nameFlip (cl, !flip)),
8776        loc))
8777     {
8778       if (sRef_isDead (other->sref))
8779         {
8780           sRef_showStateInfo (other->sref);
8781         }
8782       else /* kept */
8783         {
8784           sRef_showAliasInfo (other->sref);
8785         }
8786       
8787       sRef_setAliasKind (res->sref, AK_ERROR, fileloc_undefined);
8788       sRef_setDefinedComplete (res->sref, fileloc_undefined);
8789       
8790       sRef_setAliasKind (other->sref, AK_ERROR, fileloc_undefined);
8791       sRef_setDefinedComplete (other->sref, fileloc_undefined);
8792     }
8793 }
8794
8795 static bool notNull (sRef sr, bool flip)
8796 {
8797   return (!sRef_definitelyNull (sr)
8798           && !(sRef_isKept (sr))
8799           && !(sRef_isDependent (sr))
8800           && !(flip ? usymtab_isProbableDeepNull (sr)
8801                : usymtab_isAltProbablyDeepNull (sr)));
8802 }
8803     
8804 void
8805 uentry_mergeState (uentry res, uentry other, fileloc loc,
8806                    bool mustReturn, bool flip, bool opt,
8807                    clause cl)
8808 {
8809   llassert (uentry_isValid (res));
8810   llassert (uentry_isValid (other));
8811
8812   llassert (res->ukind == other->ukind);
8813   llassert (res->ukind == KVAR);
8814
8815   DPRINTF (("Merge state: %s / %s", 
8816             uentry_unparse (res),
8817             uentry_unparse (other)));
8818
8819   if (sRef_isValid (res->sref))
8820     {
8821       if (!mustReturn)
8822         {
8823           if (incompatibleStates (res->sref, other->sref))
8824             {
8825               if (sRef_isThroughArrayFetch (res->sref)
8826                   && !context_getFlag (FLG_STRICTBRANCHSTATE))
8827                 {
8828                   if (sRef_isKept (res->sref) || sRef_isKept (other->sref))
8829                     {
8830                       sRef_maybeKill (res->sref, loc);
8831                     }
8832                   else if (sRef_isPossiblyDead (other->sref))
8833                     {
8834                       sRef_maybeKill (res->sref, loc);
8835                     }
8836                   else
8837                     {
8838                       ;
8839                     }
8840                 }
8841               else
8842                 {
8843                   if (notNull (other->sref, flip))
8844                     {
8845                       if (sRef_isLocalParamVar (res->sref) 
8846                           && (sRef_isLocalState (other->sref) 
8847                               || sRef_isDependent (other->sref)))
8848                         {
8849                           if (sRef_isDependent (res->sref))
8850                             {
8851                               sRef_setDependent (other->sref, loc);
8852                             }
8853                           else
8854                             {
8855                               sRef_setDefState (res->sref, SS_UNUSEABLE, loc);
8856                             }
8857                         }
8858                       else 
8859                         {
8860                           branchStateError (res, other, flip, cl, loc);
8861                         }
8862                     }
8863                 }
8864               
8865               if (sRef_isKept (res->sref))
8866                 {
8867                   sRef_setKept (other->sref, loc);
8868                 }
8869             }
8870           else
8871             {
8872               if (incompatibleStates (other->sref, res->sref))
8873                 {
8874                   if (notNull (res->sref, !flip))
8875                     {
8876                       if (sRef_isLocalParamVar (res->sref) 
8877                           && (sRef_isDependent (res->sref)
8878                               || sRef_isLocalState (res->sref)))
8879                         {
8880                           if (sRef_isDependent (other->sref))
8881                             {
8882                               sRef_setDependent (res->sref, loc);
8883                             }
8884                           else
8885                             {
8886                               sRef_setDefState (res->sref, SS_UNUSEABLE, loc);
8887                             }
8888                         }
8889                       else
8890                         {
8891                           if (sRef_isParam (other->sref))
8892                             {
8893                               /* 
8894                               ** If the local variable associated
8895                               ** with the param has the correct state,
8896                               ** its okay.
8897                               ** (e.g., free (s); s = new(); ...
8898                               */
8899
8900                               uentry uvar = usymtab_lookupSafe (other->uname);
8901
8902                               if (uentry_isValid (uvar)
8903                                   && ((sRef_isDead (other->sref) 
8904                                        && sRef_isOnly (uvar->sref))
8905                                       || (sRef_isDependent (other->sref)
8906                                           && sRef_isOwned (uvar->sref))))
8907                                 {
8908                                   /* no error */
8909                                 }
8910                               else
8911                                 {
8912                                   branchStateAltError (res, other,
8913                                                        flip, cl, loc);
8914                                 }
8915                             }
8916                           else
8917                             {
8918                               branchStateAltError (res, other, 
8919                                                    flip, cl, loc);
8920                             }
8921                         }
8922                     }
8923                 }
8924
8925               if (sRef_isKept (other->sref))
8926                 {
8927                   sRef_setKept (res->sref, loc);
8928                 }
8929             }
8930           
8931           if (opt)
8932             {
8933               DPRINTF (("Merge opt..."));
8934               sRef_mergeOptState (res->sref, other->sref, cl, loc);
8935               DPRINTF (("Done!"));
8936             }
8937           else
8938             {
8939               sRef_mergeState (res->sref, other->sref, cl, loc);
8940             }
8941         }
8942       else
8943         {
8944           if (sRef_isModified (other->sref))
8945             {
8946               sRef_setModified (res->sref);
8947             }
8948         }
8949
8950       if (cl == DOWHILECLAUSE)
8951         {
8952           res->used = other->used || res->used;
8953           res->lset = other->lset || res->lset;
8954           res->uses = filelocList_append (res->uses, other->uses);
8955           other->uses = filelocList_undefined;
8956         }
8957       else
8958         {
8959           if (sRef_isMacroParamRef (res->sref)
8960               && !uentry_isSefParam (other)
8961               && !uentry_isSefParam (res))
8962             {
8963               bool hasError = FALSE;
8964               
8965               if (bool_equal (res->used, other->used))
8966                 {
8967                   res->used = other->used;
8968                 }
8969               else
8970                 {
8971                   if (other->used && !flip)
8972                     {
8973                       hasError = 
8974                         optgenerror 
8975                           (FLG_MACROPARAMS,
8976                            message ("Macro parameter %q used in true clause, "
8977                                     "but not in false clause",
8978                                     uentry_getName (res)),
8979                            uentry_whereDeclared (res));
8980                     }
8981                   else
8982                     {   
8983                       hasError = 
8984                         optgenerror 
8985                           (FLG_MACROPARAMS,
8986                            message ("Macro parameter %q used in false clause, "
8987                                     "but not in true clause",
8988                                     uentry_getName (res)),
8989                            uentry_whereDeclared (res));
8990                     }
8991                   res->used = TRUE;
8992                   
8993                   if (hasError)
8994                     {
8995                       /* make it sef now, prevent more errors */
8996                       res->info->var->kind = VKREFSEFPARAM;
8997                     }
8998                 }
8999             }
9000           else
9001             {
9002               res->used = other->used || res->used;
9003               res->lset = other->lset || res->lset;
9004               res->uses = filelocList_append (res->uses, other->uses);
9005               other->uses = filelocList_undefined;
9006             }
9007         }
9008     }
9009 }
9010
9011 void uentry_setUsed (uentry e, fileloc loc)
9012 {
9013   static bool firstTime = TRUE;
9014   static bool showUses = FALSE;
9015   static bool exportLocal = FALSE;
9016
9017   if (firstTime)
9018     {
9019       /* need to track uses is FLG_SHOWUSES or FLG_EXPORTLOCAL is true */
9020
9021       showUses = context_getFlag (FLG_SHOWUSES); 
9022       exportLocal = context_maybeSet (FLG_EXPORTLOCAL);
9023
9024       firstTime = FALSE;
9025     }
9026
9027   if (uentry_isValid (e))
9028     {
9029       int dp;
9030       
9031       if (sRef_isMacroParamRef (e->sref))
9032         {
9033           if (uentry_isYield (e) || uentry_isSefParam (e))
9034             {
9035               ;
9036             }
9037           else 
9038             {
9039               if (context_inConditional ())
9040                 {
9041                   if (optgenerror
9042                       (FLG_MACROPARAMS,
9043                        message ("Macro parameter %q used in conditionally "
9044                                 "executed code (may or may not be "
9045                                 "evaluated exactly once)", 
9046                                 uentry_getName (e)),
9047                        loc))
9048                     {
9049                       e->info->var->kind = VKREFSEFPARAM;
9050                     }
9051                 }
9052               else
9053                 {
9054                   if ((e)->used)
9055                     {
9056                       if (optgenerror
9057                           (FLG_MACROPARAMS,
9058                            message ("Macro parameter %q used more than once", 
9059                                     uentry_getName (e)),
9060                            uentry_whereDeclared (e)))
9061                         {
9062                           e->info->var->kind = VKREFSEFPARAM;
9063                         }
9064                     }
9065                 }
9066             }
9067         }
9068       
9069       if ((dp = uentry_directParamNo (e)) >= 0)
9070         {
9071           uentry_setUsed (usymtab_getParam (dp), loc);
9072         }
9073       
9074       e->used = TRUE;
9075       
9076       if (!sRef_isLocalVar (e->sref))
9077         {
9078           if (showUses)
9079             {
9080               e->uses = filelocList_add (e->uses, fileloc_copy (loc));
9081             }
9082           else 
9083             {
9084               if (exportLocal)
9085                 {
9086                   if (context_inMacro ())
9087                     {
9088                       e->uses = filelocList_addUndefined (e->uses);
9089                     }
9090                   else 
9091                     {
9092                       e->uses = filelocList_addDifferentFile
9093                         (e->uses, 
9094                          uentry_whereDeclared (e),
9095                          loc);
9096                     }
9097                 }
9098             }
9099         }
9100     }
9101 }
9102
9103 bool uentry_isReturned (uentry u)
9104 {
9105   return (uentry_isValid (u) && uentry_isVar (u) 
9106           && (u->info->var->kind == VKRETPARAM
9107               || u->info->var->kind == VKSEFRETPARAM));
9108 }
9109
9110 /*@exposed@*/ sRef uentry_returnedRef (uentry u, exprNodeList args)
9111 {
9112   llassert (uentry_isRealFunction (u));
9113
9114   if (ctype_isFunction (u->utype)
9115       && sRef_isStateSpecial (uentry_getSref (u)))
9116     {
9117       specialClauses clauses = uentry_getSpecialClauses (u);
9118       sRef res = sRef_makeNew (ctype_returnValue (u->utype), u->sref, u->uname);
9119
9120       sRef_setAllocated (res, g_currentloc);
9121
9122       specialClauses_postElements (clauses, cl)
9123         {
9124           sRefSet refs = specialClause_getRefs (cl);
9125           sRefMod modf = specialClause_getEffectFunction (cl);
9126
9127           sRefSet_elements (refs, el)
9128             {
9129               sRef base = sRef_getRootBase (el);
9130
9131               if (sRef_isResult (base))
9132                 {
9133                   if (modf != NULL)
9134                     {
9135                       sRef sr = sRef_fixBase (el, res);
9136                       modf (sr, g_currentloc);
9137                     }
9138                 }
9139               else
9140                 {
9141                   ;
9142                 }
9143             } end_sRefSet_elements ;
9144
9145         } end_specialClauses_postElements ;
9146
9147       return res;
9148     }
9149   else
9150     {
9151       uentryList params;
9152       alkind ak;
9153       sRefSet prefs = sRefSet_new ();
9154       sRef res = sRef_undefined;
9155       int paramno = 0;
9156       
9157       params = uentry_getParams (u);
9158       
9159       uentryList_elements (params, current)
9160         {
9161           if (uentry_isReturned (current))
9162             {
9163               if (exprNodeList_size (args) >= paramno)
9164                 {
9165                   exprNode ecur = exprNodeList_nth (args, paramno);
9166                   sRef tref = exprNode_getSref (ecur);
9167                   
9168                   if (sRef_isValid (tref))
9169                     {
9170                       sRef tcref = sRef_copy (tref);
9171                       
9172                       if (sRef_isDead (tcref))
9173                         {
9174                           sRef_setDefined (tcref, g_currentloc);
9175                           sRef_setOnly (tcref, g_currentloc);
9176                         }
9177                       
9178                       if (sRef_isRefCounted (tcref))
9179                         {
9180                           /* could be a new ref now (but only if its returned) */
9181                           sRef_setAliasKindComplete (tcref, AK_ERROR, g_currentloc);
9182                         }
9183                       
9184                       sRef_makeSafe (tcref);
9185                       
9186                       prefs = sRefSet_insert (prefs, tcref);
9187                     }
9188                 }
9189             }
9190           
9191           paramno++;
9192         } end_uentryList_elements ;
9193       
9194       if (sRefSet_size (prefs) > 0)
9195         {
9196           nstate n = sRef_getNullState (u->sref);
9197           
9198           if (sRefSet_size (prefs) == 1)
9199             {
9200               res = sRefSet_choose (prefs);
9201             }
9202           else
9203             {
9204               res = sRefSet_mergeIntoOne (prefs);
9205             }
9206           
9207           if (nstate_isKnown (n))
9208             {
9209               sRef_setNullState (res, n, g_currentloc);
9210             }
9211         }
9212       else
9213         {
9214           if (ctype_isFunction (u->utype))
9215             {
9216               res = sRef_makeNew (ctype_returnValue (u->utype), u->sref, u->uname);
9217             }
9218           else
9219             {
9220               res = sRef_makeNew (ctype_unknown, u->sref, u->uname);
9221             }
9222           
9223           if (sRef_isRefCounted (res))
9224             {
9225               sRef_setAliasKind (res, AK_NEWREF, g_currentloc);
9226             }
9227         }
9228       
9229       if (sRef_getNullState (res) == NS_ABSNULL)
9230         {
9231           ctype ct = ctype_realType (u->utype);
9232           
9233           if (ctype_isAbstract (ct))
9234             {
9235               sRef_setNotNull (res, g_currentloc);
9236             }
9237           else
9238             {
9239               if (ctype_isUser (ct))
9240                 {
9241                   sRef_setStateFromUentry (res, usymtab_getTypeEntry (ctype_typeId (ct)));
9242                 }
9243               else
9244                 {
9245                   sRef_setNotNull (res, g_currentloc);
9246                 }
9247             }
9248         }
9249       
9250       if (sRef_isRefCounted (res))
9251         {
9252           sRef_setAliasKind (res, AK_NEWREF, g_currentloc);
9253         }
9254       else if (sRef_isKillRef (res))
9255         {
9256           sRef_setAliasKind (res, AK_REFCOUNTED, g_currentloc);
9257         }
9258       else
9259         {
9260           ;
9261         }
9262       
9263       ak = sRef_getAliasKind (res);
9264       
9265       if (alkind_isImplicit (ak))
9266         {
9267           sRef_setAliasKind (res, 
9268                              alkind_fixImplicit (ak),
9269                              g_currentloc);
9270         }
9271       
9272       sRefSet_free (prefs);
9273       
9274       return res;
9275     }
9276 }
9277
9278 static bool uentry_isRefCounted (uentry ue)
9279 {
9280   ctype ct = uentry_getType (ue);
9281
9282   if (ctype_isFunction (ct))
9283     {
9284       return (ctype_isRefCounted (ctype_returnValue (ct)));
9285     }
9286   else
9287     {
9288       return (ctype_isRefCounted (ct));
9289     }
9290 }
9291
9292 /*
9293 ** old was declared yield in the specification.  
9294 ** new is declared in the iter implementation.
9295 */
9296
9297 void uentry_checkYieldParam (uentry old, uentry unew)
9298 {
9299   cstring name;
9300
9301   llassert (uentry_isVariable (old));
9302   llassert (uentry_isVariable (unew));
9303
9304   unew->info->var->kind = VKYIELDPARAM;
9305   (void) checkTypeConformance (old, unew, TRUE);
9306   checkVarConformance (old, unew, TRUE, FALSE);
9307
9308   /* get rid of param marker */
9309
9310   name = uentry_getName (unew);
9311   cstring_free (unew->uname);
9312   unew->uname = name;
9313   unew->info->var->kind = VKREFYIELDPARAM;
9314
9315   uentry_setUsed (old, fileloc_undefined);
9316   uentry_setUsed (unew, fileloc_undefined);
9317 }
9318
9319 /*@observer@*/ cstring
9320 uentry_ekindName (uentry ue)
9321 {
9322   if (uentry_isValid (ue))
9323     {
9324       switch (ue->ukind)
9325         {
9326         case KINVALID:
9327           return cstring_makeLiteralTemp ("<Error: invalid uentry>");
9328         case KDATATYPE: 
9329           return cstring_makeLiteralTemp ("Datatype");
9330         case KENUMCONST:
9331           return cstring_makeLiteralTemp ("Enum member");
9332         case KCONST:  
9333           return cstring_makeLiteralTemp ("Constant");
9334         case KVAR:      
9335           if (uentry_isParam (ue))
9336             {
9337               return cstring_makeLiteralTemp ("Parameter");
9338             }
9339           else if (uentry_isExpandedMacro (ue))
9340             {
9341               return cstring_makeLiteralTemp ("Expanded macro");
9342             }
9343           else
9344             {
9345               return cstring_makeLiteralTemp ("Variable");
9346             }
9347         case KFCN:   
9348           return cstring_makeLiteralTemp ("Function");
9349         case KITER: 
9350           return cstring_makeLiteralTemp ("Iterator");
9351         case KENDITER:
9352           return cstring_makeLiteralTemp ("Iterator finalizer");
9353         case KSTRUCTTAG:
9354           return cstring_makeLiteralTemp ("Struct tag");
9355         case KUNIONTAG:
9356           return cstring_makeLiteralTemp ("Union tag");
9357         case KENUMTAG: 
9358           return cstring_makeLiteralTemp ("Enum tag");
9359         case KELIPSMARKER: 
9360           return cstring_makeLiteralTemp ("Optional parameters");
9361         }
9362     }
9363   else
9364     {
9365       return cstring_makeLiteralTemp ("<Undefined>");
9366     }
9367
9368   BADEXIT;
9369 }
9370
9371 void uentry_setHasNameError (uentry ue)
9372 {
9373   llassert (uentry_isValid (ue));
9374
9375   ue->hasNameError = TRUE;
9376 }
9377
9378 void uentry_checkName (uentry ue)
9379 {
9380   if (uentry_isValid (ue) 
9381       && !uentry_isElipsisMarker (ue)
9382       && context_getFlag (FLG_NAMECHECKS)
9383       && !ue->hasNameError 
9384       && !uentry_isEndIter (ue)
9385       && !fileloc_isBuiltin (uentry_whereLast (ue))
9386       && (uentry_isExpandedMacro (ue) || !uentry_isForward (ue)))
9387     {
9388       
9389       if (uentry_isPriv (ue))
9390         {
9391           ; /* any checks here? */
9392         }
9393       else if (fileloc_isExternal (uentry_whereDefined (ue)))
9394         {
9395           ; /* no errors for externals */
9396         }
9397       else
9398         {
9399           int scope;
9400           
9401           if (uentry_isExpandedMacro (ue))
9402             {
9403               scope = globScope;
9404             }
9405           else
9406             {
9407               if (uentry_isExpandedMacro (ue))
9408                 {
9409                   scope = fileScope;
9410                 }
9411               else if (uentry_isVariable (ue))
9412                 {
9413                   sRef sr = uentry_getSref (ue);
9414
9415                   if (sRef_isValid (sr))
9416                     {
9417                       scope = sRef_getScope (sr);
9418                     }
9419                   else
9420                     {
9421                       scope = fileScope; 
9422                     }
9423                 }
9424               else if (uentry_isFunction (ue)
9425                        || uentry_isIter (ue)
9426                        || uentry_isEndIter (ue)
9427                        || uentry_isConstant (ue))
9428                 {
9429                   scope = uentry_isStatic (ue) ? fileScope : globScope;
9430                 }
9431               else /* datatypes, etc. must be global */
9432                 {
9433                   scope = globScope;
9434                 }
9435               
9436               usymtab_checkDistinctName (ue, scope);
9437             }
9438
9439           if (context_getFlag (FLG_CPPNAMES)) 
9440             {
9441               if (checkCppName (uentry_rawName (ue), uentry_whereLast (ue)))
9442                 {
9443                   uentry_setHasNameError (ue);
9444                 }
9445             }
9446
9447           if (scope == globScope)
9448             {
9449               checkGlobalName (ue);
9450
9451               if (context_getFlag (FLG_ANSIRESERVED))
9452                 {
9453                   if (uentry_hasName (ue)
9454                       && !uentry_isAnyTag (ue))
9455                     {
9456                       if (checkAnsiName (uentry_rawName (ue),
9457                                          uentry_whereLast (ue)))
9458                         {
9459                           uentry_setHasNameError (ue);
9460                         }
9461                     }
9462                 }
9463             }
9464           else
9465             {
9466               checkLocalName (ue);
9467               
9468               if (context_getFlag (FLG_ANSIRESERVEDLOCAL))
9469                 {
9470                   if (uentry_hasName (ue)
9471                       && !uentry_isAnyTag (ue))
9472                     {
9473                       if (checkAnsiName (uentry_rawName (ue),
9474                                          uentry_whereLast (ue)))
9475                         {
9476                           uentry_setHasNameError (ue);
9477                         }
9478                     }
9479                 }
9480             }
9481
9482           DPRINTF (("Check prefix: %s", uentry_unparse (ue)));
9483           checkPrefix (ue);
9484         }
9485     }
9486 }
9487
9488 /*@exposed@*/ uentry uentry_makeUnrecognized (cstring c, /*@keep@*/ fileloc loc)
9489 {
9490   uentry ue;
9491   fileloc tloc;
9492
9493   /*
9494   ** Can't but unrecognized ids in macros in global scope, because srefs will break! */
9495   if (!context_inMacro ())
9496     {
9497       sRef_setGlobalScopeSafe ();
9498     }
9499
9500   ue = uentry_makeVariable (c, ctype_unknown, loc, FALSE);
9501   uentry_setUsed (ue, loc);               
9502   
9503   tloc = fileloc_createExternal ();
9504   uentry_setDefined (ue, tloc);
9505   fileloc_free (tloc);
9506   uentry_setHasNameError (ue);
9507   
9508   if (context_getFlag (FLG_REPEATUNRECOG))
9509     {
9510       uentry_markOwned (ue);
9511     }
9512   else
9513     {
9514       ue = usymtab_supReturnFileEntry (ue);
9515     }
9516   
9517   if (!context_inMacro ())
9518     {
9519       sRef_clearGlobalScopeSafe ();
9520     }
9521
9522   return ue;
9523 }
9524
9525 /* new start modifications */
9526
9527 void uentry_testInRange (uentry p_e, uentry cconstant)  {
9528   if( uentry_isValid(p_e) ) {
9529     if( p_e->sref != NULL) {
9530         int index = atoi(exprNode_unparse(cconstant) );
9531          usymtab_testInRange (p_e->sref, index);
9532     }//end if
9533   }//endif
9534 }
9535
9536 void uentry_setStringLength (uentry p_e, uentry cconstant)  {
9537 if( uentry_isValid(p_e) ) {
9538   if( p_e->info != NULL) {
9539     if( p_e->info->var != NULL) {
9540       int length = atoi(exprNode_unparse(cconstant) ); 
9541       p_e->info->var->bufinfo->len = length; 
9542       p_e->sref->bufinfo.len = length;
9543       printf("Set string length of buff to %d \n",  p_e->sref->bufinfo.size);
9544     }//end if
9545   }//endif
9546 }//end if
9547 }
9548
9549
9550 void uentry_setBufferSize (uentry p_e, exprNode cconstant) {
9551 if( uentry_isValid(p_e) ) {
9552   if( p_e->info != NULL) {
9553     if( p_e->info->var != NULL) {
9554       int size = atoi(exprNode_unparse(cconstant) ); 
9555       p_e->info->var->bufinfo->size = size; 
9556       p_e->sref->bufinfo.size = size;
9557       printf("Set buffer size to %d \n",  p_e->sref->bufinfo.size);
9558       //  fprintf(stderr, "For %s and %s\n", uentry_unparse(p_e) );
9559       // fprintf(stderr, "and %d\n", size );
9560       
9561     }//end if
9562   }//endif
9563 }//end if
9564 }
9565
9566   
9567 /* start modifications */
9568 /*
9569 requires: p_e is defined, is a ptr/array variable 
9570 modifies: p_e
9571 effects: sets the state of the variable
9572 */
9573
9574 void uentry_setPossiblyNullTerminatedState (uentry p_e)  {
9575   if( uentry_isValid(p_e) ) {
9576     if( p_e->info != NULL) {
9577       if( p_e->info->var != NULL) {
9578          p_e->info->var->bufinfo->bufstate = BB_POSSIBLYNULLTERMINATED;
9579          p_e->sref->bufinfo.bufstate = BB_POSSIBLYNULLTERMINATED;
9580          return;
9581       }/* End if */
9582     }/* End if */
9583   }/* End if */
9584
9585   fprintf(stderr, "uentry:Error in setPossiblyNullTerminatedState\n");
9586 }
9587
9588 /*
9589 requires: p_e is defined, is a ptr/array variable 
9590 modifies: p_e
9591 effects: sets the size of the buffer
9592 */
9593
9594 void uentry_setNullTerminatedState (uentry p_e)  {
9595   if( uentry_isValid(p_e) ) {
9596     if( p_e->info != NULL) {
9597       if( p_e->info->var != NULL) {
9598         p_e->info->var->bufinfo->bufstate = BB_NULLTERMINATED;
9599         p_e->sref->bufinfo.bufstate = BB_NULLTERMINATED;
9600         return;
9601       }//End if
9602     }//End if
9603   }//End if
9604
9605   fprintf(stderr, "uentry:Error in setNullTerminatedState\n");
9606 }
9607
9608
9609 /*
9610 requires: p_e is defined, is a ptr/array variable 
9611 modifies: p_e
9612 effects: sets the state of the variable
9613 */
9614
9615 void uentry_setNotNullTerminatedState (uentry p_e)  {
9616   if( uentry_isValid(p_e) ) {
9617     if( p_e->info != NULL) {
9618       if( p_e->info->var != NULL) {
9619         p_e->info->var->bufinfo->bufstate = BB_NOTNULLTERMINATED;
9620         p_e->sref->bufinfo.bufstate = BB_NOTNULLTERMINATED;
9621         return;
9622       }//End if
9623     }//End if
9624   }//End if
9625
9626   fprintf(stderr, "uentry:Error in setNotNullTerminatedState\n");
9627 }
9628
9629
9630 /*
9631 requires: p_e is defined, is a ptr/array variable 
9632 modifies: p_e
9633 effects: sets the size of the buffer
9634 */
9635
9636 void uentry_setSize (uentry p_e, int size)  {
9637   if( uentry_isValid(p_e) ) {
9638     if( p_e->info != NULL) {
9639       if( p_e->info->var != NULL) {
9640         p_e->info->var->bufinfo->size = size;
9641         p_e->sref->bufinfo.size = size;
9642         return;
9643       }//End if
9644     }//End if
9645   }//End if
9646
9647   fprintf(stderr, "uentry:Error in setSize\n");
9648 }
9649
9650
9651 /*
9652 requires: p_e is defined, is a ptr/array variable 
9653 modifies: p_e
9654 effects: sets the length of the buffer
9655 */
9656
9657 void uentry_setLen (uentry p_e, int len)  {
9658   if( uentry_isValid(p_e) ) {
9659     if( p_e->info != NULL) {
9660       if( p_e->info->var != NULL) {
9661         p_e->info->var->bufinfo->len = len;
9662         p_e->sref->bufinfo.len = len;
9663         return;
9664       }//End if
9665     }//End if
9666   }//End if
9667
9668   fprintf(stderr, "uentry:Error in setLen\n");
9669 }
9670
9671
This page took 0.832134 seconds and 5 git commands to generate.