]> andersk Git - splint.git/blob - src/usymtab_interface.c
9509586491d4b59b7306c93e7ed8bae02c0bcea5
[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 "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, 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   usymId 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
953   declareExposedType (exposedNode n, bool priv)
954 {
955   usymId uid;
956   qtype c;
957   cstring s;
958
959   
960   if (n == (exposedNode) 0)
961     {
962       return;
963     }
964
965   c = convertLclTypeSpecNode (n->type);
966
967   declaratorInvNodeList_elements (n->decls, i)
968   {
969     ctype realType = convertTypeExpr (qtype_getType (c), i->declarator->type);
970     fileloc loc = fileloc_fromTok (i->declarator->id);
971     uentry ue;
972
973     s = getVarName (i->declarator->type);
974
975     ue = uentry_makeDatatypeAux (s, realType, MAYBE, qual_createConcrete (), 
976                                  loc, priv);
977
978     uentry_reflectQualifiers (ue, qtype_getQuals (c));
979     
980     if (context_inLCLLib () && !priv)
981       {
982         uentry_setDefined (ue, loc);
983       }
984
985     uid = usymtab_supExposedTypeEntry (ue, context_inLCLLib () && !priv);
986   } end_declaratorInvNodeList_elements;
987
988   qtype_free (c);
989 }
990
991 /*
992 ** ah...remember ye old days...
993 **
994 ** wow...same thing in THREE symbol tables!  talk about space efficiency
995 ** (or as Joe Theory once said, its only a constant factor)
996 */
997
998 void
999 doDeclareType (typeNode t, bool priv)
1000 {
1001   
1002   if (t != (typeNode) 0)
1003     {
1004       switch (t->kind)
1005         {
1006         case TK_ABSTRACT:
1007           declareAbstractType (t->content.abstract, priv);
1008           break;
1009           
1010         case TK_EXPOSED:
1011           declareExposedType (t->content.exposed, priv);
1012           break;
1013           
1014         case TK_UNION:
1015         default:
1016           {
1017             llfatalbug (message ("declareType ERROR: unknown kind: %q",
1018                                  cstring_fromCharsO (FormatInt ((int)t->kind))));
1019           }
1020         }
1021     }
1022   
1023 }
1024
1025 extern void
1026 declareIter (iterNode iter)
1027 {
1028   fileloc loc = fileloc_fromTok (iter->name);
1029   uentry ue = 
1030     uentry_makeIter (ltoken_unparse (iter->name), 
1031                      ctype_makeFunction 
1032                      (ctype_void,
1033                       paramNodeList_toUentryList (iter->params)), 
1034                      fileloc_copy (loc));
1035   
1036   usymtab_supEntry (ue);
1037   usymtab_supEntry 
1038     (uentry_makeEndIter (ltoken_unparse (iter->name), loc));
1039 }
1040
1041 /*
1042 ** declareFcn
1043 */
1044
1045 static void
1046 declareFcnAux (fcnNode f, /*@only@*/ qtype qt, ctype ct,
1047                typeId tn, bool priv, bool spec)
1048 {
1049   globalList globals;
1050   typeIdSet acct;
1051   sRefSet sl = sRefSet_undefined;
1052   globSet globlist = globSet_undefined;
1053   cstring s = getVarName (f->declarator->type);
1054   fileloc loc = fileloc_fromTok (f->declarator->id);
1055   uentryList args;
1056
1057   /*
1058   ** type conversion generates args 
1059   */
1060
1061   if (ctype_isFunction (ct))
1062     {
1063       args = ctype_argsFunction (ct);
1064     }
1065   else
1066     {
1067       llcontbug (message ("Not function: %s", ctype_unparse (ct)));
1068       args = uentryList_undefined;
1069     }
1070
1071   
1072   fileloc_setColumnUndefined (loc);
1073
1074   if (spec)
1075     {
1076       globals = f->globals;
1077       
1078       sl = fixModifies (f, args);
1079
1080       /*
1081       ** Bind let declarations in modifies list 
1082       */
1083
1084       varDeclarationNodeList_elements (globals, glob)
1085         {
1086           globlist = processGlob (globlist, glob);
1087         } end_varDeclarationNodeList_elements;
1088       
1089       
1090       if (f->checks != (lclPredicateNode) 0)
1091         /* push stderr on globalList */
1092         /* modifies *stderr^ */
1093         {
1094           uentry ue;
1095
1096           if (!(usymtab_existsVar (cstring_makeLiteralTemp ("stderr"))))
1097             {
1098               ctype tfile;
1099               
1100               llmsglit ("Global stderr implied by checks clause, "
1101                         "not declared in initializations.");
1102
1103               tfile = usymtab_lookupType (cstring_makeLiteralTemp ("FILE"));
1104               
1105               if (ctype_isUndefined (tfile))
1106                 {
1107                   llmsglit ("FILE datatype implied by checks clause not defined.");
1108                   tfile = ctype_unknown;
1109                 }
1110               
1111               usymtab_supGlobalEntry 
1112                 (uentry_makeVariable (cstring_makeLiteralTemp ("stderr"), 
1113                                      tfile, fileloc_getBuiltin (), FALSE));
1114             }
1115           
1116           ue = usymtab_lookupGlob (cstring_makeLiteralTemp ("stderr"));
1117           
1118           globlist = globSet_insert (globlist, sRef_copy (uentry_getSref (ue)));
1119           sl = sRefSet_insert (sl, sRef_buildPointer (uentry_getSref (ue)));
1120         }
1121     }
1122
1123   if (usymId_isInvalid (tn))
1124     {
1125       acct = context_fileAccessTypes ();
1126     }
1127   else
1128     {
1129       acct = typeIdSet_single (tn);
1130     }
1131
1132   if (usymtab_exists (s))
1133     {
1134       uentry l = usymtab_lookup (s);
1135       uentry ue;
1136
1137       if (uentry_isForward (l) || (fileloc_isLib (uentry_whereSpecified (l))))
1138         {
1139           typeIdSet accessType;
1140
1141           if (uentry_isFunction (l))
1142             {
1143               accessType = typeIdSet_union (uentry_accessType (l), 
1144                                             context_fileAccessTypes ());
1145             }
1146           else
1147             {
1148               accessType = context_fileAccessTypes ();
1149             }
1150
1151           if (spec)
1152             {
1153               ue = uentry_makeSpecFunction (s, ct, accessType, globlist, sl, loc);
1154             }
1155           else
1156             {
1157               sRefSet_free (sl);
1158               globSet_free (globlist);
1159
1160               ue = uentry_makeUnspecFunction (s, ct, accessType, loc);
1161             }
1162
1163           uentry_reflectQualifiers (ue, qtype_getQuals (qt));
1164           usymtab_supEntry (ue);
1165         }
1166       else
1167         {
1168           /*
1169           ** error reported by symtable already
1170           **
1171           ** llgenerror (message ("Function redeclared: %s (previous declaration: %s)", s,
1172           **                  fileloc_unparse (uentry_whereSpecified (l))),
1173           **          loc);
1174           */
1175
1176           fileloc_free (loc);
1177           sRefSet_free (sl);
1178           globSet_free (globlist);
1179         }
1180     }
1181   else
1182     {
1183       uentry le;
1184       
1185       if (spec)
1186         {
1187           if (priv)
1188             {
1189               le = uentry_makePrivFunction2 (s, ct, acct, globlist, sl, loc);
1190             }
1191           else
1192             {
1193               le = uentry_makeSpecFunction (s, ct, acct, globlist, sl, loc);
1194             }
1195         }
1196       else
1197         {
1198           le = uentry_makeUnspecFunction (s, ct, acct, loc);
1199
1200           sRefSet_free (sl);
1201           globSet_free (globlist);
1202         }
1203
1204       if (context_inLCLLib () && !priv)
1205         {
1206           uentry_setDefined (le, loc);
1207         }      
1208
1209       uentry_reflectQualifiers (le, qtype_getQuals (qt));
1210
1211       if (qual_isUnknown (f->special)) {
1212         ;
1213       } else if (qual_isPrintfLike (f->special)) {
1214         uentry_setPrintfLike (le); 
1215       } else if (qual_isScanfLike (f->special)) {
1216         uentry_setScanfLike (le); 
1217       } else if (qual_isMessageLike (f->special)) {
1218         uentry_setMessageLike (le); 
1219       } else {
1220         BADBRANCH;
1221       }
1222
1223       usymtab_supEntry (le);
1224     }
1225
1226   qtype_free (qt);
1227 }
1228
1229 extern void
1230 doDeclareFcn (fcnNode f, typeId tn, bool priv, bool spec)
1231 {
1232   qtype qt = convertLclTypeSpecNode (f->typespec);
1233   ctype ct = convertTypeExpr (qtype_getType (qt), f->declarator->type);
1234
1235   declareFcnAux (f, qt, ct, tn, priv, spec);
1236 }
1237
1238 /*
1239 ** is s is an argument to f, return its arg no.
1240 ** otherwise, return 0
1241 */
1242
1243 static int
1244 getParamNo (cstring s, fcnNode f)
1245 {
1246   /* gasp, maybe should do run-time checks here */
1247   paramNodeList params;
1248   typeExpr fd = f->declarator->type;
1249   
1250   /* is this a bug in the LCL grammar? */
1251
1252   while (fd != NULL && (fd->kind == TEXPR_PTR || fd->kind == TEXPR_ARRAY))
1253     {
1254       if (fd->kind == TEXPR_PTR)
1255         {
1256           fd = fd->content.pointer;
1257         }
1258       else
1259         {
1260           /*@-null@*/ fd = fd->content.array.elementtype; /*@=null@*/
1261          
1262           /*
1263           ** This is a bug in checking, that I should eventually fix.
1264           ** Need some way of deleting the guard from the true branch,
1265           ** but adding it back in the false branch...
1266           */
1267         }
1268     }
1269
1270   llassert (fd != NULL);
1271
1272   if (fd->kind != TEXPR_FCN)
1273     {
1274       llfatalbug (message ("getParamNo: not a function: %q (%d)",
1275                            typeExpr_unparse (fd), (int) fd->kind));
1276     }
1277
1278   params = fd->content.function.args;
1279
1280   if (paramNodeList_empty (params))
1281     {
1282       return -1;
1283     }
1284   else
1285     {
1286       int pno = 0;
1287
1288       paramNodeList_elements (params, i)
1289         {
1290           if (i->paramdecl != (typeExpr) 0)     /* handle (void) */
1291             {
1292               if (cstring_equal (s, getVarName (i->paramdecl)))
1293                 {
1294                   return pno;
1295                 }
1296             }
1297           pno++;
1298         } end_paramNodeList_elements;
1299       return -1;
1300     }
1301 }
1302
1303 static /*@null@*/ /*@observer@*/ termNode
1304 getLetDecl (cstring s, fcnNode f)
1305 {
1306   letDeclNodeList x = f->lets;
1307
1308   letDeclNodeList_elements (x, i)
1309   {
1310     if (cstring_equal (s, ltoken_getRawString (i->varid)))
1311       {
1312         if (i->sortspec != NULL)
1313           {
1314             llbuglit ("getLetDecl: cannot return sort!");
1315           }
1316         else
1317           {                     /* is a termNode */
1318             return i->term;
1319           }
1320       }
1321   } end_letDeclNodeList_elements;
1322
1323   return (termNode) 0;
1324 }
1325
1326 /*
1327 ** processTermNode --- based on printTermNode2
1328 */
1329
1330 static /*@exposed@*/ sRef 
1331   processTermNode (/*@null@*/ opFormNode op, termNodeList args, 
1332                    fcnNode f, uentryList cl)
1333 {
1334   if (op != (opFormNode) 0)
1335     {
1336       switch (op->kind)
1337         {
1338         case OPF_IF:
1339           llcontbuglit ("processTermNode: OPF_IF: not handled");
1340           break;
1341         case OPF_ANYOP:
1342           llcontbuglit ("processTermNode: OPF_ANYOP: not handled");
1343           break;
1344         case OPF_MANYOP:
1345           {
1346             int size = termNodeList_size (args);
1347
1348             if (size == 1 
1349                 && (cstring_equalLit (ltoken_getRawString (op->content.anyop), "'") ||
1350                     cstring_equalLit (ltoken_getRawString (op->content.anyop), "^")))
1351               {
1352                 return (fixTermNode (termNodeList_head (args), f, cl));
1353               }
1354             else 
1355               {
1356                 ;
1357               }
1358             break;
1359           }
1360         case OPF_ANYOPM:
1361           {
1362             int size = termNodeList_size (args);
1363
1364             if (size == 1 
1365                 && (cstring_equalLit (ltoken_getRawString (op->content.anyop), "*")))
1366               {
1367                 sRef ft;
1368                 sRef res;
1369
1370                 ft = fixTermNode (termNodeList_head (args), f, cl);
1371                 res = sRef_buildPointer (ft);
1372                 return (res);
1373               }
1374             else
1375               {
1376                 ;
1377               }
1378             break;
1379           }
1380         case OPF_MANYOPM:
1381           llcontbuglit ("OPF_MANYOPM: not handled\n");
1382           break;
1383         case OPF_MIDDLE:
1384           llcontbuglit ("OPF_MIDDLE: not handled\n");
1385           break;
1386         case OPF_MMIDDLE:
1387           llcontbuglit ("OPF_MMIDDLE: not handled\n");
1388           break;
1389         case OPF_MIDDLEM:
1390           llcontbuglit ("OPF_MIDDLEM: not handled\n");
1391           break;
1392         case OPF_MMIDDLEM:
1393           llcontbuglit ("OPF_MMIDDLEM: not handled\n");
1394           break;
1395         case OPF_BMIDDLE:
1396           if (op->content.middle == 1)
1397             llbug (message ("array fetch: [%q]",
1398                             termNodeList_unparse (args)));
1399           else
1400             llcontbuglit ("OPF_BMIDDLE: bad\n");
1401           break;
1402
1403         case OPF_BMMIDDLE:
1404           if (op->content.middle <= 1)
1405             {
1406               sRef arr = fixTermNode (termNodeList_head (args), f, cl);
1407               sRef ret;
1408
1409               if (op->content.middle == 1)
1410                 {
1411                   termNode t = (termNodeList_reset (args),
1412                                 termNodeList_advance (args),
1413                                 termNodeList_current (args));
1414                   
1415                   if (t->kind == TRM_LITERAL)
1416                     {
1417                       int i;
1418
1419                       if (sscanf 
1420                           (cstring_toCharsSafe 
1421                            (ltoken_getRawString (t->literal)),
1422                            "%d", &i) == 1)
1423                         {
1424                           ret = sRef_buildArrayFetchKnown (arr, i);
1425                         }
1426                       else
1427                         {
1428                           ret = sRef_buildArrayFetch (arr);
1429                         }
1430
1431                       return (ret);
1432                     }
1433                 }
1434                       
1435               /* unknown index */
1436
1437               ret = sRef_buildArrayFetch (arr);
1438
1439               return (ret);
1440             }
1441           else 
1442             {
1443               llcontbug (message ("op->content.middle = %d", 
1444                                   op->content.middle));
1445               break;
1446             }
1447
1448         case OPF_BMIDDLEM:
1449           llcontbuglit ("OPF_BMIDDLEM not handled");
1450           break; 
1451
1452         case OPF_BMMIDDLEM:
1453           llcontbuglit ("OPF_BMMIDDLEM not handled");
1454           break;
1455
1456         case OPF_SELECT:
1457           llcontbug (message ("select: .%s", 
1458                               ltoken_getRawString (op->content.id)));
1459           break; 
1460
1461         case OPF_MAP:
1462           llcontbug (message ("map: .%s", 
1463                               ltoken_getRawString (op->content.id)));
1464           break;
1465
1466         case OPF_MSELECT:
1467           {
1468             sRef rec = fixTermNode (termNodeList_head (args), f, cl);
1469             sRef ret; 
1470             ctype ct = ctype_realType (sRef_deriveType (rec, cl));
1471             cstring fieldname = ltoken_getRawString (op->content.id);
1472
1473             ct = ctype_realType (ct);
1474
1475             /*
1476             ** does it correspond to a typedef struct field
1477             **
1478             ** (kind of kludgey, but there is no direct way to
1479             **  tell if it is an lsl operator instead)
1480             */
1481             
1482             if (ctype_isStructorUnion (ct) &&
1483                 uentry_isValid 
1484                 (uentryList_lookupField (ctype_getFields (ct), fieldname)))
1485               {
1486                 cstring fname = cstring_copy (fieldname);
1487
1488                 ret = sRef_buildField (rec, fname);
1489                 cstring_markOwned (fname);
1490               }
1491             else
1492               {
1493                 ret = sRef_undefined;
1494               }
1495
1496             return ret;
1497           }
1498         case OPF_MMAP: 
1499           {
1500             sRef rec = fixTermNode (termNodeList_head (args), f, cl);
1501             sRef ret = sRef_undefined;
1502             ctype ct = ctype_realType (sRef_deriveType (rec, cl));
1503             cstring fieldname = ltoken_getRawString (op->content.id);
1504
1505             /*
1506             ** does it correspond to a typedef struct field
1507             */
1508             
1509             if (ctype_isPointer (ct))
1510               {
1511                 ctype ctb = ctype_realType (ctype_baseArrayPtr (ct));
1512
1513                 if (ctype_isStructorUnion (ctb) &&
1514                     uentry_isValid (uentryList_lookupField
1515                                     (ctype_getFields (ctb), fieldname)))
1516                   {
1517                     cstring fname = cstring_copy (fieldname);
1518
1519                     ret = sRef_buildArrow (rec, fname);
1520                     cstring_markOwned (fname);
1521                   }
1522               }
1523
1524             return ret;
1525           }
1526         }
1527     }
1528
1529   return sRef_undefined;
1530 }
1531
1532 /*
1533 ** fixModifies
1534 **
1535 ** o replace anything in modifies that is bound with let with value
1536 ** o replace spec variables with internal state 
1537 ** o replace paramaters with paramno identifiers
1538 ** o replace globals with their usymid's
1539 ** o make everything sRefs
1540 */
1541
1542 static /*@exposed@*/ sRef fixTermNode (termNode n, fcnNode f, uentryList cl)
1543 {
1544   if (n != (termNode) 0)
1545     {
1546       switch (n->kind)
1547         {
1548         case TRM_LITERAL:
1549           break;
1550         case TRM_CONST:
1551         case TRM_VAR:
1552         case TRM_ZEROARY:
1553           {
1554             cstring s = ltoken_getRawString (n->literal);
1555             termNode tl = getLetDecl (s, f);
1556
1557             if (tl != (termNode) 0)
1558               {
1559                 return (fixTermNode (tl, f, cl));
1560               }
1561             else
1562               {
1563                 int i = getParamNo (s, f);
1564
1565                 if (i < 0)
1566                   {
1567                     usymId usym = usymtab_getId (s);
1568                     
1569                     if (usymId_isInvalid (usym))
1570                       {
1571                         if (usymtab_existsEither (s))
1572                           {
1573                             return sRef_makeSpecState ();
1574                           }
1575                         else
1576                           {
1577                             llcontbuglit ("Invalid symbol in modifies list");
1578                             return sRef_undefined;
1579                           }
1580                       }
1581                     else
1582                       return (sRef_makeGlobal (usym, ctype_unknown, stateInfo_currentLoc ()));
1583                   }
1584                 
1585                 else
1586                   {
1587                     sRef p = sRef_makeParam (i, ctype_unknown, stateInfo_currentLoc ());
1588                     return (p);
1589                   }
1590               }
1591           }
1592         case TRM_APPLICATION:
1593           {
1594             nameNode nn = n->name;
1595
1596             if (nn != (nameNode) 0)
1597               {
1598                 if (nn->isOpId)
1599                   {
1600                     /* must we handle n->given ? skip for now */
1601
1602                     llfatalbug 
1603                       (message ("fixTermNode: expect non-empty nameNode: "
1604                                 "TRM_APPLICATION: %q",
1605                                 nameNode_unparse (nn)));
1606                   }
1607                 else
1608                   {
1609                     sRef sr;
1610
1611                     sr = processTermNode (nn->content.opform, n->args, f, cl);
1612                                     return (sr);
1613                   }
1614               }
1615             
1616             return sRef_undefined;
1617           }
1618         case TRM_UNCHANGEDALL:      
1619         case TRM_UNCHANGEDOTHERS:
1620         case TRM_SIZEOF:
1621         case TRM_QUANTIFIER:
1622           return sRef_undefined;
1623         }
1624     }
1625
1626   return sRef_undefined;
1627 }
1628
1629 static 
1630 /*@only@*/ sRefSet fixModifies (fcnNode f, uentryList cl)
1631 {
1632   static bool shownWarning = FALSE;
1633   modifyNode m = f->modify;
1634   sRefSet sl = sRefSet_new ();
1635
1636   if (m != (modifyNode) 0)
1637     {
1638       if (m->hasStoreRefList)
1639         {
1640           storeRefNodeList srefs = m->list;
1641
1642           storeRefNodeList_elements (srefs, i)
1643             {
1644               if (storeRefNode_isObj (i) || storeRefNode_isType (i))
1645                 {
1646                   if (!shownWarning)
1647                     {
1648                       fileloc loc = fileloc_fromTok (f->name);
1649                   
1650                       llmsg (message
1651                              ("%q: Warning: object and type modifications "
1652                               "not understood by Splint",
1653                               fileloc_unparse (loc)));
1654                       fileloc_free (loc);
1655                       shownWarning = TRUE;
1656                     }
1657                 }
1658               else if (storeRefNode_isSpecial (i))
1659                 {
1660                   sl = sRefSet_insert (sl, i->content.ref);
1661                 }
1662               else if (storeRefNode_isTerm (i))
1663                 {
1664                   sRef s = fixTermNode (i->content.term, f, cl);
1665
1666                   if (sRef_isKnown (s)) 
1667                     {
1668                       sl = sRefSet_insert (sl, s);
1669                     }
1670                 }
1671               else
1672                 {
1673                   BADEXIT;
1674                 }
1675             } end_storeRefNodeList_elements;
1676           
1677         }
1678     }
1679
1680   return sl;
1681 }
1682
1683 static /*@only@*/ cstring
1684 paramNode_name (paramNode x)
1685 {
1686   return (typeExpr_name (x->paramdecl));
1687 }
1688
1689 static /*@only@*/ uentry
1690 paramNode_toUentry (paramNode p)
1691 {
1692   if (p != (paramNode) 0)
1693     {
1694       if (p->kind == PELIPSIS)
1695         {
1696           return uentry_makeElipsisMarker ();
1697         }
1698       else
1699         {
1700           qtype ct = convertLclTypeSpecNode (p->type);
1701           ctype cr = convertTypeExpr (qtype_getType (ct), p->paramdecl);
1702           cstring pname = (p->paramdecl == (typeExpr)0) ? cstring_undefined 
1703                                                         : paramNode_name (p);
1704           uentry ue = uentry_makeVariableParam (pname, cr, g_currentloc);
1705
1706           uentry_reflectQualifiers (ue, qtype_getQuals (ct));
1707           qtype_free (ct);
1708           return (ue);
1709         }
1710     }
1711   else
1712     {
1713       llcontbuglit ("paramNode_toUentry: NULL");
1714       return uentry_undefined;
1715     }
1716   BADEXIT;
1717 }
1718
1719 static uentryList
1720   paramNodeList_toUentryList (paramNodeList p)
1721 {
1722   uentryList cl = uentryList_new ();
1723
1724   if (paramNodeList_isNull (p)) return (cl);
1725
1726   paramNodeList_elements (p, current)
1727     {
1728       cl = uentryList_add (cl, paramNode_toUentry (current));
1729     } end_paramNodeList_elements;
1730
1731   return cl;
1732 }
1733
1734
This page took 0.178291 seconds and 3 git commands to generate.