]> andersk Git - splint.git/blob - src/usymtab_interface.c
Fixed preds.expect for name change.
[splint.git] / src / usymtab_interface.c
1 /*
2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2002 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://www.splint.org
23 */
24 /*
25 ** usymtab_interface.c
26 **
27 ** Grammar interface to symtab.
28 **
29 ** The Splint parser will build symbol tables for abstract types and
30 ** function declarations.
31 **
32 */
33
34 # include "lclintMacros.nf"
35 # include "llbasic.h"
36 # include "gram.h"
37 # include "lclscan.h"
38 # include "lclsyntable.h"
39 # include "lslparse.h"
40 # include "usymtab_interface.h"
41 # include "structNames.h"
42
43 static void 
44   declareFcnAux (fcnNode p_f, /*@only@*/ qtype p_qt, ctype p_ct, typeId p_tn, 
45                  bool p_priv, bool p_spec);
46
47 static uentryList paramNodeList_toUentryList (paramNodeList p_p);
48 static /*@observer@*/ cstring getVarName (/*@null@*/ typeExpr p_x);
49 static qtype convertLclTypeSpecNode (/*@null@*/ lclTypeSpecNode p_n);
50 static ctype convertTypeExpr (ctype p_c, /*@null@*/ typeExpr p_x);
51 static ctype convertCTypeExpr (ctype p_c, /*@null@*/ typeExpr p_x);
52 static /*@exposed@*/ sRef fixTermNode (termNode p_n, fcnNode p_f, uentryList p_cl);
53 static sRefSet fixModifies (fcnNode p_f, uentryList p_cl);
54
55 static uentryList
56   convertuentryList (stDeclNodeList x)
57 {
58   uentryList fl = uentryList_new ();
59
60   
61   stDeclNodeList_elements (x, i)
62   {
63     declaratorNodeList d = i->declarators;
64     qtype q = convertLclTypeSpecNode (i->lcltypespec);
65
66     declaratorNodeList_elements (d, j)
67     {
68       idDecl id;
69
70       qtype_setType (q, convertTypeExpr (qtype_getType (q), j->type));
71       id = idDecl_create (cstring_copy (getVarName (j->type)), qtype_copy (q));
72       fl = uentryList_add (fl, uentry_makeIdVariable (id));
73       idDecl_free (id);
74     } end_declaratorNodeList_elements;
75
76     qtype_free (q);
77   } end_stDeclNodeList_elements;
78
79   
80   return (fl);
81 }
82
83 static uentryList
84   convert_uentryList (paramNodeList x)
85 {
86   uentryList p = uentryList_undefined;
87   bool first_one = TRUE;
88
89   
90   paramNodeList_elements (x, i)
91   {
92     if (i != (paramNode) 0)
93       {
94         if (paramNode_isElipsis (i))
95           {
96             first_one = FALSE;
97             p = uentryList_add (p, uentry_makeElipsisMarker ());
98           }
99         else
100           {
101             qtype q = convertLclTypeSpecNode (i->type);
102             typeExpr t = i->paramdecl;
103             
104             qtype_setType (q, convertTypeExpr (qtype_getType (q), t));
105             
106             /* note: has to be like this to hack around void  ???? still */ 
107
108             if (first_one)
109               {
110                 if (ctype_isVoid (qtype_getType (q)))
111                   {
112                     llassert (uentryList_isUndefined (p));
113                     qtype_free (q);
114                     return (p);
115                   }
116                 
117                 first_one = FALSE;
118               }
119             
120             /*
121             ** don't do qualifiers here, will get errors later
122             */
123
124             p = uentryList_add (p, uentry_makeUnnamedVariable (qtype_getType (q)));
125             qtype_free (q);
126           }
127       }
128     else
129       {
130         llbug (cstring_makeLiteral ("convertuentryList: null paramNode"));
131       }
132   } end_paramNodeList_elements;
133   
134   if (first_one)
135     {
136       llassert (uentryList_isUndefined (p));
137       
138       p = uentryList_makeMissingParams ();
139     }
140
141   return p;
142 }
143
144 /*
145 ** convertTypeExpr
146 **
147 ** modify c with pointer, array, function
148 **
149 ** (based on printTypeExpr2 from abstract.c)
150 **
151 */
152
153 static ctype
154 convertTypeExpr (ctype c, typeExpr x)
155 {
156   if (x == (typeExpr) 0)
157     {
158       return c;
159     }
160   
161   switch (x->kind)
162     {
163     case TEXPR_BASE:
164       return (c);
165     case TEXPR_PTR:
166       return (convertTypeExpr (ctype_makePointer (c), x->content.pointer));
167     case TEXPR_ARRAY:
168       return (convertTypeExpr (ctype_makeArray (c), x->content.array.elementtype));
169     case TEXPR_FCN:
170       {
171         ctype rv = convertTypeExpr (c, x->content.function.returntype);
172         uentryList p = paramNodeList_toUentryList (x->content.function.args);
173         
174         if (x->content.function.returntype != NULL
175             && x->content.function.returntype->wrapped == 1 
176             && ctype_isPointer (rv))
177           {
178             rv = ctype_baseArrayPtr (rv);
179           }
180
181         return (ctype_makeParamsFunction (rv, p));
182       }
183     default:
184       {
185         llfatalbug (message ("convertTypeExpr: unknown typeExprKind: %d",
186                              (int) x->kind));
187       }
188     }
189
190   BADEXIT;
191 }
192
193 static 
194 ctype convertCTypeExpr (ctype c, typeExpr x)
195 {
196   if (x == (typeExpr) 0)
197     {
198       return c;
199     }
200
201   switch (x->kind)
202     {
203     case TEXPR_BASE:     return (c);
204     case TEXPR_PTR:  return (convertCTypeExpr (ctype_makePointer (c), 
205                                                  x->content.pointer));
206     case TEXPR_ARRAY:    return (convertCTypeExpr (ctype_makeArray (c), 
207                                                  x->content.array.elementtype));
208     case TEXPR_FCN:
209       {
210         ctype rv = convertCTypeExpr (c, x->content.function.returntype);
211         uentryList p = convert_uentryList (x->content.function.args);
212
213         return (ctype_makeParamsFunction (rv, p));
214       }
215     default:
216       {
217         llfatalbug (message ("convertCTypeExpr: unknown typeExprKind: %d", (int) x->kind));
218       }
219     }
220   BADEXIT;
221 }
222
223 /*
224 ** convertLclTypeSpecNode
225 **
226 ** LclTypeSpecNode --> ctype
227 ** this is the base type only!
228 */
229
230 /*
231 ** convertLeaves
232 **
233 ** for now, assume only last leaf is relevant.
234 ** this should be a safe assumption in general???
235 */
236
237 static ctype
238   convertLeaves (ltokenList f)
239 {
240   ctype c = ctype_unknown;
241   
242   ltokenList_reset (f);
243   
244   ltokenList_elements (f, current)
245     {
246       switch (ltoken_getCode (current))
247         {
248         case LLT_TYPEDEF_NAME:
249           {
250             cstring tn = ltoken_getRawString (current);
251
252             if (usymtab_existsTypeEither (tn))
253               {
254                 c = ctype_combine (uentry_getAbstractType 
255                                    (usymtab_lookupEither (tn)), c);
256               }
257             else if (cstring_equalLit (tn, "bool"))
258               {
259                 /*
260                 ** Bogus...keep consistent with old lcl builtin.
261                 */
262                 c = ctype_bool;
263               }
264             else
265               {
266                 fileloc loc = fileloc_fromTok (current);
267
268                 voptgenerror (FLG_UNRECOG, 
269                               message ("Unrecognized type: %s", tn), loc);
270                 fileloc_free (loc);
271                 
272                 usymtab_supEntry 
273                   (uentry_makeDatatype 
274                    (tn, ctype_unknown, MAYBE, NO, fileloc_getBuiltin ()));
275                 
276               }
277             /*@switchbreak@*/ break;
278           }
279         case LLT_CHAR:
280           c = ctype_combine (ctype_char, c);
281           /*@switchbreak@*/ break;
282           
283         case LLT_DOUBLE:
284           c = ctype_combine (ctype_double, c);
285           /*@switchbreak@*/ break;
286         case LLT_FLOAT:     
287           c = ctype_combine (ctype_float, c);
288           /*@switchbreak@*/ break;
289         case LLT_CONST:    
290         case LLT_VOLATILE: 
291           /*@switchbreak@*/ break;
292         case LLT_INT:      
293           c = ctype_combine (ctype_int, c);
294           /*@switchbreak@*/ break;
295         case LLT_LONG:  
296           c = ctype_combine (c, ctype_lint); 
297           /*@switchbreak@*/ break;
298         case LLT_SHORT:    
299           c = ctype_combine (c, ctype_sint);
300           /*@switchbreak@*/ break;
301         case LLT_SIGNED:    
302           c = ctype_combine (c, ctype_int); 
303           /*@switchbreak@*/ break;
304         case LLT_UNSIGNED:  
305           c = ctype_combine (c, ctype_uint);
306           /*@switchbreak@*/ break;
307         case LLT_UNKNOWN:   
308           c = ctype_combine (ctype_unknown, c);
309           /*@switchbreak@*/ break;
310         case LLT_VOID:      
311           c = ctype_combine (ctype_void, c); 
312           /*@switchbreak@*/ break;
313         case LLT_ENUM:
314           llcontbug (cstring_makeLiteral ("convertLeaves: enum"));
315           c = ctype_int; 
316           /*@switchbreak@*/ break;
317         default:
318           llfatalbug (message ("convertLeaves: bad token: %q", 
319                                ltoken_unparseCodeName (current)));
320         }
321     } end_ltokenList_elements;
322
323   return c;
324 }
325
326 static enumNameList
327   convertEnumList (ltokenList enums)
328 {
329   enumNameList el = enumNameList_new ();
330
331   if (ltokenList_isDefined (enums))
332     {
333       ltokenList_elements (enums, i)
334         {
335           enumNameList_addh 
336             (el, enumName_create (cstring_copy (ltoken_unparse (i))));
337         } end_ltokenList_elements;
338     }
339
340   return el;
341 }
342
343 static /*@only@*/ qtype 
344   convertLclTypeSpecNode (/*@null@*/ lclTypeSpecNode n)
345 {
346   
347   if (n != (lclTypeSpecNode) 0)
348     {
349       qtype result;
350       
351       switch (n->kind)
352         {
353         case LTS_CONJ:
354           {
355             qtype c1 = convertLclTypeSpecNode (n->content.conj->a);
356             qtype c2 = convertLclTypeSpecNode (n->content.conj->b);
357
358             /*
359             ** Is it explicit?
360             */
361
362             if (fileloc_isLib (g_currentloc)
363                 || fileloc_isStandardLibrary (g_currentloc))
364               {
365                 result = qtype_mergeImplicitAlt (c1, c2);
366               }
367             else
368               {
369                 result = qtype_mergeAlt (c1, c2);
370               }
371             
372             break;
373           }
374         case LTS_TYPE:
375           llassert (n->content.type != NULL);
376           result = qtype_create (convertLeaves (n->content.type->ctypes));
377           break;
378         case LTS_STRUCTUNION:
379           {
380             strOrUnionNode sn;
381             cstring cn = cstring_undefined;
382
383             sn = n->content.structorunion;
384
385             llassert (sn != (strOrUnionNode) 0);
386
387             if (!ltoken_isUndefined (sn->opttagid))
388               {
389                 cn = cstring_copy (ltoken_getRawString (sn->opttagid));
390               }
391             else
392               {
393                 cn = fakeTag ();
394               }
395
396             switch (sn->kind)
397               {
398               case SU_STRUCT:
399                 if (usymtab_existsStructTag (cn))
400                   {
401                     
402                     result = qtype_create (uentry_getAbstractType
403                                            (usymtab_lookupStructTag (cn)));
404                     cstring_free (cn);
405                   }
406                 else
407                   {
408                     uentryList fl = convertuentryList (sn->structdecls);
409                     ctype ct;
410
411                                     ct = ctype_createStruct (cstring_copy (cn), fl);
412
413                     /*
414                     ** If it was a forward declaration, this could add it to
415                     ** the table.  Need to check if it exists again...
416                     */
417
418                     if (usymtab_existsStructTag (cn))
419                       {
420                         result = qtype_create (uentry_getAbstractType
421                                                (usymtab_lookupStructTag (cn)));
422                       }
423                     else
424                       {
425                         fileloc loc = fileloc_fromTok (n->content.structorunion->tok);
426                         uentry ue = uentry_makeStructTag (cn, ct, loc);
427
428                         result = qtype_create (usymtab_supTypeEntry (ue));
429                       }
430                         
431                     cstring_free (cn);
432                   }
433                 /*@switchbreak@*/ break;
434               case SU_UNION:
435                 if (usymtab_existsUnionTag (cn))
436                   {
437                     
438                     result = qtype_create (uentry_getAbstractType
439                                            (usymtab_lookupUnionTag (cn)));
440                     cstring_free (cn);
441                   }
442                 else
443                   {
444                     uentryList fl;
445                     ctype ct;
446                     
447                     fl = convertuentryList (sn->structdecls);
448                     ct = ctype_createUnion (cstring_copy (cn), fl);
449
450                     /*
451                     ** If it was a forward declaration, this could add it to
452                     ** the table.  Need to check if it exists again...
453                     */
454
455                     
456                     
457                     if (usymtab_existsUnionTag (cn))
458                       {
459                         
460                         result = qtype_create (uentry_getAbstractType
461                                                (usymtab_lookupUnionTag (cn)));
462                       }
463                     else
464                       {
465                         fileloc loc = fileloc_fromTok (n->content.structorunion->tok);
466                         uentry ue = uentry_makeUnionTag (cn, ct, loc);
467
468                         result = qtype_create (usymtab_supTypeEntry (ue));
469                       }
470                         
471                     cstring_free (cn);
472                   }
473                 /*@switchbreak@*/ break;
474               BADDEFAULT
475               }
476             break;
477           }
478         case LTS_ENUM:
479           {
480             enumSpecNode e = n->content.enumspec;
481             enumNameList el;
482             cstring ename;
483             bool first = TRUE;
484             ctype ta;
485             ctype cet;
486
487             llassert (e != NULL);
488             el = convertEnumList (e->enums);
489
490             if (!ltoken_isUndefined (e->opttagid))      /* named enumerator */
491               {
492                 ename = cstring_copy (ltoken_getRawString (e->opttagid));
493               }
494             else
495               {
496                 ename = fakeTag ();
497               }
498
499             cet = ctype_createEnum (ename, el);
500             
501             if (usymtab_existsEnumTag (ename))
502               {
503                 ta = uentry_getAbstractType (usymtab_lookupEnumTag (ename));
504               }
505             else
506               { 
507                 fileloc loc = fileloc_fromTok (e->tok);
508                 uentry ue = uentry_makeEnumTag (ename, cet, loc);
509
510                 ta = usymtab_supTypeEntry (ue);
511               }
512
513             enumNameList_elements (el, en)
514               {
515                 uentry ue;
516                 fileloc loc;
517
518                 if (first)
519                   {
520                     ltokenList_reset (e->enums);
521                     first = FALSE;
522                   }
523                 else
524                   {
525                     ltokenList_advance (e->enums);
526                   }
527
528                 loc = fileloc_fromTok (ltokenList_current (e->enums));
529                 ue = uentry_makeSpecEnumConstant (en, cet, loc);
530
531                 /*
532                 ** Can't check name here, might not have
533                 ** type yet.  Will check in .lh file?
534                 */
535                 
536                 ue = usymtab_supGlobalEntryReturn (ue);
537                 
538                 if (context_inLCLLib ())
539                   {
540                     uentry_setDefined (ue, loc);
541                   }
542               } end_enumNameList_elements;
543             
544             result = qtype_create (ta);
545           }
546           break;
547         default:
548           {
549             llfatalbug (message ("convertLclTypeSpecNode: unknown lclTypeSpec kind: %d",
550                                  (int) n->kind));
551           }
552         }
553       
554       result = qtype_addQualList (result, n->quals);
555
556       if (n->pointers > 0)
557         {
558           qtype_adjustPointers (n->pointers, result);
559         }
560
561       return result;
562     }
563   else
564     {
565       llcontbug (cstring_makeLiteral ("convertLclTypeSpecNode: null"));
566       return qtype_unknown (); 
567     }
568   BADEXIT;
569
570
571 static /*@only@*/ multiVal
572   literalValue (ctype ct, ltoken lit)
573 {
574   cstring text = cstring_fromChars (lsymbol_toChars (ltoken_getText (lit)));
575   char first;
576
577   if (cstring_length (text) > 0)
578     {
579       first = cstring_firstChar (text);
580     }
581   else
582     {
583       return multiVal_unknown ();
584     }
585
586   
587   if /*@-usedef@*/ (first == '\"') /*@=usedef@*/
588     {
589       int len = cstring_length (text) - 2;
590       char *val = mstring_create (len);
591       
592       llassert (cstring_lastChar (text) == '\"');
593       strncpy (val, cstring_toCharsSafe (text) + 1, size_fromInt (len));
594       return (multiVal_makeString (cstring_fromCharsO (val)));
595     }
596
597   if (ctype_isDirectInt (ct) || ctype_isPointer (ct))
598     {
599       long val = 0;
600      
601       if (sscanf (cstring_toCharsSafe (text), "%ld", &val) == 1)
602         {
603           return multiVal_makeInt (val);
604         }
605     }
606
607   return multiVal_unknown ();
608 }
609
610
611 /*
612 ** declareConstant
613 **
614 ** unfortunately, because the abstract types are different, this
615 ** cannot be easily subsumed into declareVar.
616 */
617
618 void
619 doDeclareConstant (constDeclarationNode c, bool priv)
620 {
621   lclTypeSpecNode t;
622   ctype ctx;
623   qtype qt;
624   
625   if (c == (constDeclarationNode) 0)
626     {
627       return;
628     }
629
630   t = c->type;
631   qt = convertLclTypeSpecNode (t);
632
633   ctx = qtype_getType (qt);
634
635   initDeclNodeList_elements (c->decls, i)
636     {
637       ctype ct = convertTypeExpr (ctx, i->declarator->type);
638       cstring s = getVarName (i->declarator->type);
639
640       if (ctype_isFunction (ct))
641         {
642           fcnNode fcn = fcnNode_fromDeclarator (lclTypeSpecNode_copy (t), 
643                                                 declaratorNode_copy (i->declarator));
644
645           /* FALSE == unspecified function, only a declaration */
646
647           doDeclareFcn (fcn, typeId_invalid, priv, FALSE);
648           fcnNode_free (fcn);
649         }
650       else
651         {
652           uentry ue;
653           fileloc loc = fileloc_fromTok (i->declarator->id);
654
655           if (i->value != (termNode)0 &&
656               i->value->kind == TRM_LITERAL)
657             {
658               ue = uentry_makeConstantValue (s, ct, loc, priv, literalValue (ct, i->value->literal));
659             }
660           else
661             {
662               ue = uentry_makeConstantValue (s, ct, loc, priv, multiVal_unknown ());
663             }
664           
665           uentry_reflectQualifiers (ue, qtype_getQuals (qt));
666           
667           if (context_inLCLLib () && !priv)
668             {
669               uentry_setDefined (ue, loc);
670             }
671
672           usymtab_supGlobalEntry (ue);
673         }
674     } end_initDeclNodeList_elements;
675
676   qtype_free (qt);
677 }
678
679 static cstring
680 getVarName (/*@null@*/ typeExpr x)
681 {
682   cstring s = cstring_undefined;
683
684   if (x != (typeExpr) 0)
685     {
686       switch (x->kind)
687         {
688         case TEXPR_BASE:
689           s = ltoken_getRawString (x->content.base);
690           break;
691         case TEXPR_PTR:
692           s = getVarName (x->content.pointer);
693           break;
694         case TEXPR_ARRAY:
695           s = getVarName (x->content.array.elementtype);
696           break;
697         case TEXPR_FCN:
698           s = getVarName (x->content.function.returntype);
699           break;
700         default:
701           llfatalbug (message ("getVarName: unknown typeExprKind: %d", (int) x->kind));
702         }
703     }
704
705   return s;
706 }
707
708 void
709 doDeclareVar (varDeclarationNode v, bool priv)
710 {
711   lclTypeSpecNode t;
712   qtype c;
713
714   if (v == (varDeclarationNode) 0)
715     {
716       return;
717     }
718
719   t = v->type;
720   c = convertLclTypeSpecNode (t);
721
722   initDeclNodeList_elements (v->decls, i)
723     {
724       ctype ct = convertTypeExpr (qtype_getType (c), i->declarator->type);
725       cstring s = getVarName (i->declarator->type);
726
727       qtype_setType (c, ct);
728
729       if (ctype_isFunction (ct))
730         {
731           fcnNode fcn;
732
733                   
734           fcn = fcnNode_fromDeclarator (lclTypeSpecNode_copy (t), 
735                                         declaratorNode_copy (i->declarator));
736
737           /* FALSE == unspecified function, only a declaration */
738           declareFcnAux (fcn, qtype_unknown (), ct,
739                          typeId_invalid, priv, FALSE);
740           fcnNode_free (fcn);
741         }
742       else
743         {
744           fileloc loc = fileloc_fromTok (i->declarator->id);
745           uentry le = uentry_makeVariable (s, ct, loc, priv);
746           
747           uentry_reflectQualifiers (le, qtype_getQuals (c));
748           
749           if (uentry_isCheckedUnknown (le))
750             {
751               if (context_getFlag (FLG_IMPCHECKEDSTRICTSPECGLOBALS))
752                 {
753                   uentry_setCheckedStrict (le);
754                 }
755               else if (context_getFlag (FLG_IMPCHECKEDSPECGLOBALS))
756                 {
757                   uentry_setChecked (le);
758                 }
759               else if (context_getFlag (FLG_IMPCHECKMODSPECGLOBALS))
760                 {
761                   uentry_setCheckMod (le);
762                 }
763               else
764                 {
765                   ; /* okay */
766                 }
767             }
768
769           if (context_inLCLLib () && !priv)
770             {
771               uentry_setDefined (le, loc);
772             }
773
774           if (initDeclNode_isRedeclaration (i))
775             {
776               usymtab_replaceEntry (le);
777             }
778           else
779             {
780               le = usymtab_supEntrySrefReturn (le);
781             }
782         }
783     } end_initDeclNodeList_elements;
784
785   qtype_free (c);
786 }
787
788 static globSet
789 processGlob (/*@returned@*/ globSet globs, varDeclarationNode v)
790 {
791   if (v == (varDeclarationNode) 0)
792     {
793       return globs;
794     }
795
796   if (v->isSpecial)
797     {
798       globs = globSet_insert (globs, v->sref);
799     }
800   else
801     {
802       lclTypeSpecNode t = v->type;
803       qtype qt = convertLclTypeSpecNode (t);
804       ctype c = qtype_getType (qt);
805       cstring s;      
806
807       initDeclNodeList_elements (v->decls, i)
808         {
809           ctype ct;
810           uentry ue;
811           qualList quals = qtype_getQuals (qt);
812           
813           s = getVarName (i->declarator->type);
814           ue = usymtab_lookupGlobSafe (s);
815           
816           if (uentry_isInvalid (ue))
817             {
818               ; /* error already reported */ 
819             }
820           else
821             {
822               if (uentry_isPriv (ue))
823                 {
824                   globs = globSet_insert (globs, sRef_makeSpecState ());
825                 }
826               else
827                 {
828                   uentry ce = uentry_copy (ue);
829                   ctype lt = uentry_getType (ce);
830                   fileloc loc = fileloc_fromTok (i->declarator->id);
831                   
832                   ct = convertTypeExpr (c, i->declarator->type);
833                   
834                   if (!ctype_match (lt, ct))
835                     {
836                       (void) gentypeerror
837                         (lt, exprNode_undefined,
838                          ct, exprNode_undefined,
839                          message ("Global type mismatch %s (%t, %t)",
840                                   s, lt, ct), 
841                          loc);
842                     }
843                   
844                   uentry_reflectQualifiers (ce, quals);
845                   globs = globSet_insert (globs,
846                                           sRef_copy (uentry_getSref (ce)));
847                   fileloc_free (loc);
848                   uentry_free (ce);
849                 }
850             }
851         } end_initDeclNodeList_elements;
852
853       qtype_free (qt);
854     }
855
856   return globs;
857 }
858
859 static void
860 declareAbstractType (abstractNode n, bool priv)
861 {
862   cstring tn;
863   fileloc loc;
864   uentry ue;
865   usymId uid;
866   abstBodyNode ab;
867
868   if (n == (abstractNode) 0)
869     {
870       return;
871     }
872
873   
874   tn = ltoken_getRawString (n->name);
875
876   loc = fileloc_fromTok (n->tok);
877   
878   ue = uentry_makeDatatypeAux (tn, ctype_unknown, 
879                                ynm_fromBool (n->isMutable), YES, loc, priv);
880
881   if (n->isRefCounted)
882     {
883       uentry_setRefCounted (ue);
884     }
885
886   if (context_inLCLLib () && !priv)
887     {
888       uentry_setDefined (ue, loc);
889     }
890
891   uid = usymtab_supAbstractTypeEntry (ue, context_inLCLLib() && !priv);
892   
893
894   if (!priv && (ab = n->body) != (abstBodyNode) 0)
895     {
896       fcnNodeList ops = ab->fcns;
897
898       if (!fcnNodeList_isEmpty (ops))
899         {
900           fcnNodeList_elements (ops, i)
901           {
902             if (i->typespec == (lclTypeSpecNode) 0)
903               {
904                 cstring fname = ltoken_getRawString (i->name);
905
906                 if (usymtab_exists (fname))
907                   {
908                     uentry e = usymtab_lookup (fname);
909                     fileloc floc = fileloc_fromTok (i->declarator->id);
910
911                     if (uentry_isForward (e))
912                       {
913                         usymtab_supEntry  
914                           (uentry_makeTypeListFunction 
915                            (fname, typeIdSet_insert (uentry_accessType (e), uid), 
916                             floc));
917                       }
918                     else
919                       {
920                         usymtab_supEntry 
921                           (uentry_makeSpecFunction 
922                            (fname, uentry_getType (e),
923                             typeIdSet_insert (uentry_accessType (e), uid),
924                             globSet_undefined,
925                             sRefSet_undefined,
926                             floc));
927                         
928                         if (context_inLCLLib ())
929                           {
930                             llbuglit ("Jolly jeepers Wilma, it ain't dead after all!");
931                           }
932                       }
933                   }
934                 else
935                   {
936                     usymtab_supEntry 
937                       (uentry_makeForwardFunction (fname, uid, loc));
938                   }
939               }
940             else
941               {
942                 declareFcn (i, uid);
943               }
944           } end_fcnNodeList_elements;
945         }
946     }
947 }
948
949 static void
950   declareExposedType (exposedNode n, bool priv)
951 {
952   usymId uid;
953   qtype c;
954   cstring s;
955
956   
957   if (n == (exposedNode) 0)
958     {
959       return;
960     }
961
962   c = convertLclTypeSpecNode (n->type);
963
964   declaratorInvNodeList_elements (n->decls, i)
965   {
966     ctype realType = convertTypeExpr (qtype_getType (c), i->declarator->type);
967     fileloc loc = fileloc_fromTok (i->declarator->id);
968     uentry ue;
969
970     s = getVarName (i->declarator->type);
971
972     ue = uentry_makeDatatypeAux (s, realType, MAYBE, NO, loc, priv);
973
974     uentry_reflectQualifiers (ue, qtype_getQuals (c));
975     
976     if (context_inLCLLib () && !priv)
977       {
978         uentry_setDefined (ue, loc);
979       }
980
981     uid = usymtab_supExposedTypeEntry (ue, context_inLCLLib () && !priv);
982   } end_declaratorInvNodeList_elements;
983
984   qtype_free (c);
985 }
986
987 /*
988 ** ah...remember ye old days...
989 **
990 ** wow...same thing in THREE symbol tables!  talk about space efficiency
991 ** (or as Joe Theory once said, its only a constant factor)
992 */
993
994 void
995 doDeclareType (typeNode t, bool priv)
996 {
997   
998   if (t != (typeNode) 0)
999     {
1000       switch (t->kind)
1001         {
1002         case TK_ABSTRACT:
1003           declareAbstractType (t->content.abstract, priv);
1004           break;
1005           
1006         case TK_EXPOSED:
1007           declareExposedType (t->content.exposed, priv);
1008           break;
1009           
1010         case TK_UNION:
1011         default:
1012           {
1013             llfatalbug (message ("declareType ERROR: unknown kind: %q",
1014                                  cstring_fromCharsO (FormatInt ((int)t->kind))));
1015           }
1016         }
1017     }
1018   
1019 }
1020
1021 extern void
1022 declareIter (iterNode iter)
1023 {
1024   fileloc loc = fileloc_fromTok (iter->name);
1025   uentry ue = 
1026     uentry_makeIter (ltoken_unparse (iter->name), 
1027                      ctype_makeFunction 
1028                      (ctype_void,
1029                       paramNodeList_toUentryList (iter->params)), 
1030                      fileloc_copy (loc));
1031   
1032   usymtab_supEntry (ue);
1033   usymtab_supEntry 
1034     (uentry_makeEndIter (ltoken_unparse (iter->name), loc));
1035 }
1036
1037 /*
1038 ** declareFcn
1039 */
1040
1041 static void
1042 declareFcnAux (fcnNode f, /*@only@*/ qtype qt, ctype ct,
1043                typeId tn, bool priv, bool spec)
1044 {
1045   globalList globals;
1046   typeIdSet acct;
1047   sRefSet sl = sRefSet_undefined;
1048   globSet globlist = globSet_undefined;
1049   cstring s = getVarName (f->declarator->type);
1050   fileloc loc = fileloc_fromTok (f->declarator->id);
1051   uentryList args;
1052
1053   /*
1054   ** type conversion generates args 
1055   */
1056
1057   if (ctype_isFunction (ct))
1058     {
1059       args = ctype_argsFunction (ct);
1060     }
1061   else
1062     {
1063       llcontbug (message ("Not function: %s", ctype_unparse (ct)));
1064       args = uentryList_undefined;
1065     }
1066
1067   
1068   fileloc_setColumnUndefined (loc);
1069
1070   if (spec)
1071     {
1072       globals = f->globals;
1073       
1074       sl = fixModifies (f, args);
1075
1076       /*
1077       ** Bind let declarations in modifies list 
1078       */
1079
1080       varDeclarationNodeList_elements (globals, glob)
1081         {
1082           globlist = processGlob (globlist, glob);
1083         } end_varDeclarationNodeList_elements;
1084       
1085       
1086       if (f->checks != (lclPredicateNode) 0)
1087         /* push stderr on globalList */
1088         /* modifies *stderr^ */
1089         {
1090           uentry ue;
1091
1092           if (!(usymtab_existsVar (cstring_makeLiteralTemp ("stderr"))))
1093             {
1094               ctype tfile;
1095               
1096               llmsglit ("Global stderr implied by checks clause, "
1097                         "not declared in initializations.");
1098
1099               tfile = usymtab_lookupType (cstring_makeLiteralTemp ("FILE"));
1100               
1101               if (ctype_isUndefined (tfile))
1102                 {
1103                   llmsglit ("FILE datatype implied by checks clause not defined.");
1104                   tfile = ctype_unknown;
1105                 }
1106               
1107               usymtab_supGlobalEntry 
1108                 (uentry_makeVariable (cstring_makeLiteralTemp ("stderr"), 
1109                                      tfile, fileloc_getBuiltin (), FALSE));
1110             }
1111           
1112           ue = usymtab_lookupGlob (cstring_makeLiteralTemp ("stderr"));
1113           
1114           globlist = globSet_insert (globlist, sRef_copy (uentry_getSref (ue)));
1115           sl = sRefSet_insert (sl, sRef_buildPointer (uentry_getSref (ue)));
1116         }
1117     }
1118
1119   if (usymId_isInvalid (tn))
1120     {
1121       acct = context_fileAccessTypes ();
1122     }
1123   else
1124     {
1125       acct = typeIdSet_single (tn);
1126     }
1127
1128   if (usymtab_exists (s))
1129     {
1130       uentry l = usymtab_lookup (s);
1131       uentry ue;
1132
1133       if (uentry_isForward (l) || (fileloc_isLib (uentry_whereSpecified (l))))
1134         {
1135           typeIdSet accessType;
1136
1137           if (uentry_isFunction (l))
1138             {
1139               accessType = typeIdSet_union (uentry_accessType (l), 
1140                                             context_fileAccessTypes ());
1141             }
1142           else
1143             {
1144               accessType = context_fileAccessTypes ();
1145             }
1146
1147           if (spec)
1148             {
1149               ue = uentry_makeSpecFunction (s, ct, accessType, globlist, sl, loc);
1150             }
1151           else
1152             {
1153               sRefSet_free (sl);
1154               globSet_free (globlist);
1155
1156               ue = uentry_makeUnspecFunction (s, ct, accessType, loc);
1157             }
1158
1159           uentry_reflectQualifiers (ue, qtype_getQuals (qt));
1160           usymtab_supEntry (ue);
1161         }
1162       else
1163         {
1164           /*
1165           ** error reported by symtable already
1166           **
1167           ** llgenerror (message ("Function redeclared: %s (previous declaration: %s)", s,
1168           **                  fileloc_unparse (uentry_whereSpecified (l))),
1169           **          loc);
1170           */
1171
1172           fileloc_free (loc);
1173           sRefSet_free (sl);
1174           globSet_free (globlist);
1175         }
1176     }
1177   else
1178     {
1179       uentry le;
1180       
1181       if (spec)
1182         {
1183           if (priv)
1184             {
1185               le = uentry_makePrivFunction2 (s, ct, acct, globlist, sl, loc);
1186             }
1187           else
1188             {
1189               le = uentry_makeSpecFunction (s, ct, acct, globlist, sl, loc);
1190             }
1191         }
1192       else
1193         {
1194           le = uentry_makeUnspecFunction (s, ct, acct, loc);
1195
1196           sRefSet_free (sl);
1197           globSet_free (globlist);
1198         }
1199
1200       if (context_inLCLLib () && !priv)
1201         {
1202           uentry_setDefined (le, loc);
1203         }      
1204
1205       uentry_reflectQualifiers (le, qtype_getQuals (qt));
1206
1207       if (qual_isUnknown (f->special)) {
1208         ;
1209       } else if (qual_isPrintfLike (f->special)) {
1210         uentry_setPrintfLike (le); 
1211       } else if (qual_isScanfLike (f->special)) {
1212         uentry_setScanfLike (le); 
1213       } else if (qual_isMessageLike (f->special)) {
1214         uentry_setMessageLike (le); 
1215       } else {
1216         BADBRANCH;
1217       }
1218
1219       usymtab_supEntry (le);
1220     }
1221
1222   qtype_free (qt);
1223 }
1224
1225 extern void
1226 doDeclareFcn (fcnNode f, typeId tn, bool priv, bool spec)
1227 {
1228   qtype qt = convertLclTypeSpecNode (f->typespec);
1229   ctype ct = convertTypeExpr (qtype_getType (qt), f->declarator->type);
1230
1231   declareFcnAux (f, qt, ct, tn, priv, spec);
1232 }
1233
1234 /*
1235 ** is s is an argument to f, return its arg no.
1236 ** otherwise, return 0
1237 */
1238
1239 static int
1240 getParamNo (cstring s, fcnNode f)
1241 {
1242   /* gasp, maybe should do run-time checks here */
1243   paramNodeList params;
1244   typeExpr fd = f->declarator->type;
1245   
1246   /* is this a bug in the LCL grammar? */
1247
1248   while (fd != NULL && (fd->kind == TEXPR_PTR || fd->kind == TEXPR_ARRAY))
1249     {
1250       if (fd->kind == TEXPR_PTR)
1251         {
1252           fd = fd->content.pointer;
1253         }
1254       else
1255         {
1256           /*@-null@*/ fd = fd->content.array.elementtype; /*@=null@*/
1257          
1258           /*
1259           ** This is a bug in checking, that I should eventually fix.
1260           ** Need some way of deleting the guard from the true branch,
1261           ** but adding it back in the false branch...
1262           */
1263         }
1264     }
1265
1266   llassert (fd != NULL);
1267
1268   if (fd->kind != TEXPR_FCN)
1269     {
1270       llfatalbug (message ("getParamNo: not a function: %q (%d)",
1271                            typeExpr_unparse (fd), (int) fd->kind));
1272     }
1273
1274   params = fd->content.function.args;
1275
1276   if (paramNodeList_empty (params))
1277     {
1278       return -1;
1279     }
1280   else
1281     {
1282       int pno = 0;
1283
1284       paramNodeList_elements (params, i)
1285         {
1286           if (i->paramdecl != (typeExpr) 0)     /* handle (void) */
1287             {
1288               if (cstring_equal (s, getVarName (i->paramdecl)))
1289                 {
1290                   return pno;
1291                 }
1292             }
1293           pno++;
1294         } end_paramNodeList_elements;
1295       return -1;
1296     }
1297 }
1298
1299 static /*@null@*/ /*@observer@*/ termNode
1300 getLetDecl (cstring s, fcnNode f)
1301 {
1302   letDeclNodeList x = f->lets;
1303
1304   letDeclNodeList_elements (x, i)
1305   {
1306     if (cstring_equal (s, ltoken_getRawString (i->varid)))
1307       {
1308         if (i->sortspec != NULL)
1309           {
1310             llbuglit ("getLetDecl: cannot return sort!");
1311           }
1312         else
1313           {                     /* is a termNode */
1314             return i->term;
1315           }
1316       }
1317   } end_letDeclNodeList_elements;
1318
1319   return (termNode) 0;
1320 }
1321
1322 /*
1323 ** processTermNode --- based on printTermNode2
1324 */
1325
1326 static /*@exposed@*/ sRef 
1327   processTermNode (/*@null@*/ opFormNode op, termNodeList args, 
1328                    fcnNode f, uentryList cl)
1329 {
1330   if (op != (opFormNode) 0)
1331     {
1332       switch (op->kind)
1333         {
1334         case OPF_IF:
1335           llcontbuglit ("processTermNode: OPF_IF: not handled");
1336           break;
1337         case OPF_ANYOP:
1338           llcontbuglit ("processTermNode: OPF_ANYOP: not handled");
1339           break;
1340         case OPF_MANYOP:
1341           {
1342             int size = termNodeList_size (args);
1343
1344             if (size == 1 
1345                 && (cstring_equalLit (ltoken_getRawString (op->content.anyop), "'") ||
1346                     cstring_equalLit (ltoken_getRawString (op->content.anyop), "^")))
1347               {
1348                 return (fixTermNode (termNodeList_head (args), f, cl));
1349               }
1350             else 
1351               {
1352                 ;
1353               }
1354             break;
1355           }
1356         case OPF_ANYOPM:
1357           {
1358             int size = termNodeList_size (args);
1359
1360             if (size == 1 
1361                 && (cstring_equalLit (ltoken_getRawString (op->content.anyop), "*")))
1362               {
1363                 sRef ft;
1364                 sRef res;
1365
1366                 ft = fixTermNode (termNodeList_head (args), f, cl);
1367                 res = sRef_buildPointer (ft);
1368                 return (res);
1369               }
1370             else
1371               {
1372                 ;
1373               }
1374             break;
1375           }
1376         case OPF_MANYOPM:
1377           llcontbuglit ("OPF_MANYOPM: not handled\n");
1378           break;
1379         case OPF_MIDDLE:
1380           llcontbuglit ("OPF_MIDDLE: not handled\n");
1381           break;
1382         case OPF_MMIDDLE:
1383           llcontbuglit ("OPF_MMIDDLE: not handled\n");
1384           break;
1385         case OPF_MIDDLEM:
1386           llcontbuglit ("OPF_MIDDLEM: not handled\n");
1387           break;
1388         case OPF_MMIDDLEM:
1389           llcontbuglit ("OPF_MMIDDLEM: not handled\n");
1390           break;
1391         case OPF_BMIDDLE:
1392           if (op->content.middle == 1)
1393             llbug (message ("array fetch: [%q]",
1394                             termNodeList_unparse (args)));
1395           else
1396             llcontbuglit ("OPF_BMIDDLE: bad\n");
1397           break;
1398
1399         case OPF_BMMIDDLE:
1400           if (op->content.middle <= 1)
1401             {
1402               sRef arr = fixTermNode (termNodeList_head (args), f, cl);
1403               sRef ret;
1404
1405               if (op->content.middle == 1)
1406                 {
1407                   termNode t = (termNodeList_reset (args),
1408                                 termNodeList_advance (args),
1409                                 termNodeList_current (args));
1410                   
1411                   if (t->kind == TRM_LITERAL)
1412                     {
1413                       int i;
1414
1415                       if (sscanf 
1416                           (cstring_toCharsSafe 
1417                            (ltoken_getRawString (t->literal)),
1418                            "%d", &i) == 1)
1419                         {
1420                           ret = sRef_buildArrayFetchKnown (arr, i);
1421                         }
1422                       else
1423                         {
1424                           ret = sRef_buildArrayFetch (arr);
1425                         }
1426
1427                       return (ret);
1428                     }
1429                 }
1430                       
1431               /* unknown index */
1432
1433               ret = sRef_buildArrayFetch (arr);
1434
1435               return (ret);
1436             }
1437           else 
1438             {
1439               llcontbug (message ("op->content.middle = %d", 
1440                                   op->content.middle));
1441               break;
1442             }
1443
1444         case OPF_BMIDDLEM:
1445           llcontbuglit ("OPF_BMIDDLEM not handled");
1446           break; 
1447
1448         case OPF_BMMIDDLEM:
1449           llcontbuglit ("OPF_BMMIDDLEM not handled");
1450           break;
1451
1452         case OPF_SELECT:
1453           llcontbug (message ("select: .%s", 
1454                               ltoken_getRawString (op->content.id)));
1455           break; 
1456
1457         case OPF_MAP:
1458           llcontbug (message ("map: .%s", 
1459                               ltoken_getRawString (op->content.id)));
1460           break;
1461
1462         case OPF_MSELECT:
1463           {
1464             sRef rec = fixTermNode (termNodeList_head (args), f, cl);
1465             sRef ret; 
1466             ctype ct = ctype_realType (sRef_deriveType (rec, cl));
1467             cstring fieldname = ltoken_getRawString (op->content.id);
1468
1469             ct = ctype_realType (ct);
1470
1471             /*
1472             ** does it correspond to a typedef struct field
1473             **
1474             ** (kind of kludgey, but there is no direct way to
1475             **  tell if it is an lsl operator instead)
1476             */
1477             
1478             if (ctype_isStructorUnion (ct) &&
1479                 uentry_isValid 
1480                 (uentryList_lookupField (ctype_getFields (ct), fieldname)))
1481               {
1482                 cstring fname = cstring_copy (fieldname);
1483
1484                 ret = sRef_buildField (rec, fname);
1485                 cstring_markOwned (fname);
1486               }
1487             else
1488               {
1489                 ret = sRef_undefined;
1490               }
1491
1492             return ret;
1493           }
1494         case OPF_MMAP: 
1495           {
1496             sRef rec = fixTermNode (termNodeList_head (args), f, cl);
1497             sRef ret = sRef_undefined;
1498             ctype ct = ctype_realType (sRef_deriveType (rec, cl));
1499             cstring fieldname = ltoken_getRawString (op->content.id);
1500
1501             /*
1502             ** does it correspond to a typedef struct field
1503             */
1504             
1505             if (ctype_isPointer (ct))
1506               {
1507                 ctype ctb = ctype_realType (ctype_baseArrayPtr (ct));
1508
1509                 if (ctype_isStructorUnion (ctb) &&
1510                     uentry_isValid (uentryList_lookupField
1511                                     (ctype_getFields (ctb), fieldname)))
1512                   {
1513                     cstring fname = cstring_copy (fieldname);
1514
1515                     ret = sRef_buildArrow (rec, fname);
1516                     cstring_markOwned (fname);
1517                   }
1518               }
1519
1520             return ret;
1521           }
1522         }
1523     }
1524
1525   return sRef_undefined;
1526 }
1527
1528 /*
1529 ** fixModifies
1530 **
1531 ** o replace anything in modifies that is bound with let with value
1532 ** o replace spec variables with internal state 
1533 ** o replace paramaters with paramno identifiers
1534 ** o replace globals with their usymid's
1535 ** o make everything sRefs
1536 */
1537
1538 static /*@exposed@*/ sRef fixTermNode (termNode n, fcnNode f, uentryList cl)
1539 {
1540   if (n != (termNode) 0)
1541     {
1542       switch (n->kind)
1543         {
1544         case TRM_LITERAL:
1545           break;
1546         case TRM_CONST:
1547         case TRM_VAR:
1548         case TRM_ZEROARY:
1549           {
1550             cstring s = ltoken_getRawString (n->literal);
1551             termNode tl = getLetDecl (s, f);
1552
1553             if (tl != (termNode) 0)
1554               {
1555                 return (fixTermNode (tl, f, cl));
1556               }
1557             else
1558               {
1559                 int i = getParamNo (s, f);
1560
1561                 if (i < 0)
1562                   {
1563                     usymId usym = usymtab_getId (s);
1564                     
1565                     if (usymId_isInvalid (usym))
1566                       {
1567                         if (usymtab_existsEither (s))
1568                           {
1569                             return sRef_makeSpecState ();
1570                           }
1571                         else
1572                           {
1573                             llcontbuglit ("Invalid symbol in modifies list");
1574                             return sRef_undefined;
1575                           }
1576                       }
1577                     else
1578                       return (sRef_makeGlobal (usym, ctype_unknown, stateInfo_currentLoc ()));
1579                   }
1580                 
1581                 else
1582                   {
1583                     sRef p = sRef_makeParam (i, ctype_unknown, stateInfo_currentLoc ());
1584                     return (p);
1585                   }
1586               }
1587           }
1588         case TRM_APPLICATION:
1589           {
1590             nameNode nn = n->name;
1591
1592             if (nn != (nameNode) 0)
1593               {
1594                 if (nn->isOpId)
1595                   {
1596                     /* must we handle n->given ? skip for now */
1597
1598                     llfatalbug 
1599                       (message ("fixTermNode: expect non-empty nameNode: "
1600                                 "TRM_APPLICATION: %q",
1601                                 nameNode_unparse (nn)));
1602                   }
1603                 else
1604                   {
1605                     sRef sr;
1606
1607                     sr = processTermNode (nn->content.opform, n->args, f, cl);
1608                                     return (sr);
1609                   }
1610               }
1611             
1612             return sRef_undefined;
1613           }
1614         case TRM_UNCHANGEDALL:      
1615         case TRM_UNCHANGEDOTHERS:
1616         case TRM_SIZEOF:
1617         case TRM_QUANTIFIER:
1618           return sRef_undefined;
1619         }
1620     }
1621
1622   return sRef_undefined;
1623 }
1624
1625 static 
1626 /*@only@*/ sRefSet fixModifies (fcnNode f, uentryList cl)
1627 {
1628   static bool shownWarning = FALSE;
1629   modifyNode m = f->modify;
1630   sRefSet sl = sRefSet_new ();
1631
1632   if (m != (modifyNode) 0)
1633     {
1634       if (m->hasStoreRefList)
1635         {
1636           storeRefNodeList srefs = m->list;
1637
1638           storeRefNodeList_elements (srefs, i)
1639             {
1640               if (storeRefNode_isObj (i) || storeRefNode_isType (i))
1641                 {
1642                   if (!shownWarning)
1643                     {
1644                       fileloc loc = fileloc_fromTok (f->name);
1645                   
1646                       llmsg (message
1647                              ("%q: Warning: object and type modifications "
1648                               "not understood by Splint",
1649                               fileloc_unparse (loc)));
1650                       fileloc_free (loc);
1651                       shownWarning = TRUE;
1652                     }
1653                 }
1654               else if (storeRefNode_isSpecial (i))
1655                 {
1656                   sl = sRefSet_insert (sl, i->content.ref);
1657                 }
1658               else if (storeRefNode_isTerm (i))
1659                 {
1660                   sRef s = fixTermNode (i->content.term, f, cl);
1661
1662                   if (sRef_isKnown (s)) 
1663                     {
1664                       sl = sRefSet_insert (sl, s);
1665                     }
1666                 }
1667               else
1668                 {
1669                   BADEXIT;
1670                 }
1671             } end_storeRefNodeList_elements;
1672           
1673         }
1674     }
1675
1676   return sl;
1677 }
1678
1679 static /*@only@*/ cstring
1680 paramNode_name (paramNode x)
1681 {
1682   return (typeExpr_name (x->paramdecl));
1683 }
1684
1685 static /*@only@*/ uentry
1686 paramNode_toUentry (paramNode p)
1687 {
1688   if (p != (paramNode) 0)
1689     {
1690       if (p->kind == PELIPSIS)
1691         {
1692           return uentry_makeElipsisMarker ();
1693         }
1694       else
1695         {
1696           qtype ct = convertLclTypeSpecNode (p->type);
1697           ctype cr = convertTypeExpr (qtype_getType (ct), p->paramdecl);
1698           cstring pname = (p->paramdecl == (typeExpr)0) ? cstring_undefined 
1699                                                         : paramNode_name (p);
1700           uentry ue = uentry_makeVariableParam (pname, cr, g_currentloc);
1701
1702           uentry_reflectQualifiers (ue, qtype_getQuals (ct));
1703           qtype_free (ct);
1704           return (ue);
1705         }
1706     }
1707   else
1708     {
1709       llcontbuglit ("paramNode_toUentry: NULL");
1710       return uentry_undefined;
1711     }
1712   BADEXIT;
1713 }
1714
1715 static uentryList
1716   paramNodeList_toUentryList (paramNodeList p)
1717 {
1718   uentryList cl = uentryList_new ();
1719
1720   if (paramNodeList_isNull (p)) return (cl);
1721
1722   paramNodeList_elements (p, current)
1723     {
1724       cl = uentryList_add (cl, paramNode_toUentry (current));
1725     } end_paramNodeList_elements;
1726
1727   return cl;
1728 }
1729
1730
This page took 0.201015 seconds and 5 git commands to generate.