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