]> andersk Git - splint.git/blob - src/usymtab_interface.c
Merged code tree with Dave Evans's version. Many changes to numberous to list....
[splint.git] / src / usymtab_interface.c
1 /*
2 ** LCLint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2001 University of Virginia,
4 **         Massachusetts Institute of Technology
5 **
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
10 ** 
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 ** General Public License for more details.
15 ** 
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
19 **
20 ** For information on lclint: lclint-request@cs.virginia.edu
21 ** To report a bug: lclint-bug@cs.virginia.edu
22 ** For more information: http://lclint.cs.virginia.edu
23 */
24 /*
25 ** usymtab_interface.c
26 **
27 ** Grammar interface to symtab.
28 **
29 ** The LCLint parser will build symbol tables for abstract types and
30 ** function declarations.
31 **
32 */
33
34 # include "lclintMacros.nf"
35 # include "llbasic.h"
36 # include "gram.h"
37 # include "lclscan.h"
38 # include "lclsyntable.h"
39 # include "lslparse.h"
40 # include "usymtab_interface.h"
41 # include "structNames.h"
42
43 static void 
44   declareFcnAux (fcnNode p_f, /*@only@*/ qtype p_qt, ctype p_ct, typeId p_tn, 
45                  bool p_priv, bool p_spec);
46
47 static uentryList paramNodeList_toUentryList (paramNodeList p_p);
48 static /*@observer@*/ cstring getVarName (/*@null@*/ typeExpr p_x);
49 static qtype convertLclTypeSpecNode (/*@null@*/ lclTypeSpecNode p_n);
50 static ctype convertTypeExpr (ctype p_c, /*@null@*/ typeExpr p_x);
51 static ctype convertCTypeExpr (ctype p_c, /*@null@*/ typeExpr p_x);
52 static /*@exposed@*/ sRef fixTermNode (termNode p_n, fcnNode p_f, uentryList p_cl);
53 static sRefSet fixModifies (fcnNode p_f, uentryList p_cl);
54
55 static uentryList
56   convertuentryList (stDeclNodeList x)
57 {
58   uentryList fl = uentryList_new ();
59
60   
61   stDeclNodeList_elements (x, i)
62   {
63     declaratorNodeList d = i->declarators;
64     qtype q = convertLclTypeSpecNode (i->lcltypespec);
65
66     declaratorNodeList_elements (d, j)
67     {
68       idDecl id;
69
70       qtype_setType (q, convertTypeExpr (qtype_getType (q), j->type));
71       id = idDecl_create (cstring_copy (getVarName (j->type)), qtype_copy (q));
72       fl = uentryList_add (fl, uentry_makeIdVariable (id));
73       idDecl_free (id);
74     } end_declaratorNodeList_elements;
75
76     qtype_free (q);
77   } end_stDeclNodeList_elements;
78
79   
80   return (fl);
81 }
82
83 static uentryList
84   convert_uentryList (paramNodeList x)
85 {
86   uentryList p = uentryList_undefined;
87   bool first_one = TRUE;
88
89   
90   paramNodeList_elements (x, i)
91   {
92     if (i != (paramNode) 0)
93       {
94         if (paramNode_isElipsis (i))
95           {
96             first_one = FALSE;
97             p = uentryList_add (p, uentry_makeElipsisMarker ());
98           }
99         else
100           {
101             qtype q = convertLclTypeSpecNode (i->type);
102             typeExpr t = i->paramdecl;
103             
104             qtype_setType (q, convertTypeExpr (qtype_getType (q), t));
105             
106             /* note: has to be like this to hack around void  ???? still */ 
107
108             if (first_one)
109               {
110                 if (ctype_isVoid (qtype_getType (q)))
111                   {
112                     llassert (uentryList_isUndefined (p));
113                     qtype_free (q);
114                     return (p);
115                   }
116                 
117                 first_one = FALSE;
118               }
119             
120             /*
121             ** don't do qualifiers here, will get errors later
122             */
123
124             p = uentryList_add (p, uentry_makeUnnamedVariable (qtype_getType (q)));
125             qtype_free (q);
126           }
127       }
128     else
129       {
130         llbug (cstring_makeLiteral ("convertuentryList: null paramNode"));
131       }
132   } end_paramNodeList_elements;
133   
134   if (first_one)
135     {
136       llassert (uentryList_isUndefined (p));
137       
138       p = uentryList_makeMissingParams ();
139     }
140
141   return p;
142 }
143
144 /*
145 ** convertTypeExpr
146 **
147 ** modify c with pointer, array, function
148 **
149 ** (based on printTypeExpr2 from abstract.c)
150 **
151 */
152
153 static ctype
154 convertTypeExpr (ctype c, typeExpr x)
155 {
156   if (x == (typeExpr) 0)
157     {
158       return c;
159     }
160   
161   switch (x->kind)
162     {
163     case TEXPR_BASE:
164       return (c);
165     case TEXPR_PTR:
166       return (convertTypeExpr (ctype_makePointer (c), x->content.pointer));
167     case TEXPR_ARRAY:
168       return (convertTypeExpr (ctype_makeArray (c), x->content.array.elementtype));
169     case TEXPR_FCN:
170       {
171         ctype rv = convertTypeExpr (c, x->content.function.returntype);
172         uentryList p = paramNodeList_toUentryList (x->content.function.args);
173         
174         if (x->content.function.returntype != NULL
175             && x->content.function.returntype->wrapped == 1 
176             && ctype_isPointer (rv))
177           {
178             rv = ctype_baseArrayPtr (rv);
179           }
180
181         return (ctype_makeParamsFunction (rv, p));
182       }
183     default:
184       {
185         llfatalbug (message ("convertTypeExpr: unknown typeExprKind: %d",
186                              (int) x->kind));
187       }
188     }
189
190   BADEXIT;
191 }
192
193 static 
194 ctype convertCTypeExpr (ctype c, typeExpr x)
195 {
196   if (x == (typeExpr) 0)
197     {
198       return c;
199     }
200
201   switch (x->kind)
202     {
203     case TEXPR_BASE:     return (c);
204     case TEXPR_PTR:  return (convertCTypeExpr (ctype_makePointer (c), 
205                                                  x->content.pointer));
206     case TEXPR_ARRAY:    return (convertCTypeExpr (ctype_makeArray (c), 
207                                                  x->content.array.elementtype));
208     case TEXPR_FCN:
209       {
210         ctype rv = convertCTypeExpr (c, x->content.function.returntype);
211         uentryList p = convert_uentryList (x->content.function.args);
212
213         return (ctype_makeParamsFunction (rv, p));
214       }
215     default:
216       {
217         llfatalbug (message ("convertCTypeExpr: unknown typeExprKind: %d", (int) x->kind));
218       }
219     }
220   BADEXIT;
221 }
222
223 /*
224 ** convertLclTypeSpecNode
225 **
226 ** LclTypeSpecNode --> ctype
227 ** this is the base type only!
228 */
229
230 /*
231 ** convertLeaves
232 **
233 ** for now, assume only last leaf is relevant.
234 ** this should be a safe assumption in general???
235 */
236
237 static ctype
238   convertLeaves (ltokenList f)
239 {
240   ctype c = ctype_unknown;
241   
242   ltokenList_reset (f);
243   
244   ltokenList_elements (f, current)
245     {
246       switch (ltoken_getCode (current))
247         {
248         case LLT_TYPEDEF_NAME:
249           {
250             cstring tn = ltoken_getRawString (current);
251
252             if (usymtab_existsTypeEither (tn))
253               {
254                 c = ctype_combine (uentry_getAbstractType 
255                                    (usymtab_lookupEither (tn)), c);
256               }
257             else if (cstring_equalLit (tn, "bool"))
258               {
259                 /*
260                 ** Bogus...keep consistent with old lcl builtin.
261                 */
262                 c = ctype_bool;
263               }
264             else
265               {
266                 fileloc loc = fileloc_fromTok (current);
267
268                 voptgenerror (FLG_UNRECOG, 
269                               message ("Unrecognized type: %s", tn), loc);
270                 fileloc_free (loc);
271                 
272                 usymtab_supEntry 
273                   (uentry_makeDatatype 
274                    (tn, ctype_unknown, MAYBE, NO, fileloc_getBuiltin ()));
275                 
276               }
277             /*@switchbreak@*/ break;
278           }
279         case LLT_CHAR:
280           c = ctype_combine (ctype_char, c);
281           /*@switchbreak@*/ break;
282           
283         case LLT_DOUBLE:
284           c = ctype_combine (ctype_double, c);
285           /*@switchbreak@*/ break;
286         case LLT_FLOAT:     
287           c = ctype_combine (ctype_float, c);
288           /*@switchbreak@*/ break;
289         case LLT_CONST:    
290         case LLT_VOLATILE: 
291           /*@switchbreak@*/ break;
292         case LLT_INT:      
293           c = ctype_combine (ctype_int, c);
294           /*@switchbreak@*/ break;
295         case LLT_LONG:  
296           c = ctype_combine (c, ctype_lint); 
297           /*@switchbreak@*/ break;
298         case LLT_SHORT:    
299           c = ctype_combine (c, ctype_sint);
300           /*@switchbreak@*/ break;
301         case LLT_SIGNED:    
302           c = ctype_combine (c, ctype_int); 
303           /*@switchbreak@*/ break;
304         case LLT_UNSIGNED:  
305           c = ctype_combine (c, ctype_uint);
306           /*@switchbreak@*/ break;
307         case LLT_UNKNOWN:   
308           c = ctype_combine (ctype_unknown, c);
309           /*@switchbreak@*/ break;
310         case LLT_VOID:      
311           c = ctype_combine (ctype_void, c); 
312           /*@switchbreak@*/ break;
313         case LLT_ENUM:
314           llcontbug (cstring_makeLiteral ("convertLeaves: enum"));
315           c = ctype_int; 
316           /*@switchbreak@*/ break;
317         default:
318           llfatalbug (message ("convertLeaves: bad token: %q", 
319                                ltoken_unparseCodeName (current)));
320         }
321     } end_ltokenList_elements;
322
323   return c;
324 }
325
326 static enumNameList
327   convertEnumList (ltokenList enums)
328 {
329   enumNameList el = enumNameList_new ();
330
331   if (ltokenList_isDefined (enums))
332     {
333       ltokenList_elements (enums, i)
334         {
335           enumNameList_addh 
336             (el, enumName_create (cstring_copy (ltoken_unparse (i))));
337         } end_ltokenList_elements;
338     }
339
340   return el;
341 }
342
343 static /*@only@*/ qtype 
344   convertLclTypeSpecNode (/*@null@*/ lclTypeSpecNode n)
345 {
346   
347   if (n != (lclTypeSpecNode) 0)
348     {
349       qtype result;
350       
351       switch (n->kind)
352         {
353         case LTS_CONJ:
354           {
355             qtype c1 = convertLclTypeSpecNode (n->content.conj->a);
356             qtype c2 = convertLclTypeSpecNode (n->content.conj->b);
357
358             /*
359             ** Is it explicit?
360             */
361
362             if (fileloc_isLib (g_currentloc)
363                 || fileloc_isStandardLibrary (g_currentloc))
364               {
365                 result = qtype_mergeImplicitAlt (c1, c2);
366               }
367             else
368               {
369                 result = qtype_mergeAlt (c1, c2);
370               }
371             
372             break;
373           }
374         case LTS_TYPE:
375           llassert (n->content.type != NULL);
376           result = qtype_create (convertLeaves (n->content.type->ctypes));
377           break;
378         case LTS_STRUCTUNION:
379           {
380             strOrUnionNode sn;
381             cstring cn = cstring_undefined;
382
383             sn = n->content.structorunion;
384
385             llassert (sn != (strOrUnionNode) 0);
386
387             if (!ltoken_isUndefined (sn->opttagid))
388               {
389                 cn = cstring_copy (ltoken_getRawString (sn->opttagid));
390               }
391             else
392               {
393                 cn = fakeTag ();
394               }
395
396             switch (sn->kind)
397               {
398               case SU_STRUCT:
399                 if (usymtab_existsStructTag (cn))
400                   {
401                     
402                     result = qtype_create (uentry_getAbstractType
403                                            (usymtab_lookupStructTag (cn)));
404                     cstring_free (cn);
405                   }
406                 else
407                   {
408                     uentryList fl = convertuentryList (sn->structdecls);
409                     ctype ct;
410
411                                     ct = ctype_createStruct (cstring_copy (cn), fl);
412
413                     /*
414                     ** If it was a forward declaration, this could add it to
415                     ** the table.  Need to check if it exists again...
416                     */
417
418                     if (usymtab_existsStructTag (cn))
419                       {
420                         result = qtype_create (uentry_getAbstractType
421                                                (usymtab_lookupStructTag (cn)));
422                       }
423                     else
424                       {
425                         fileloc loc = fileloc_fromTok (n->content.structorunion->tok);
426                         uentry ue = uentry_makeStructTag (cn, ct, loc);
427
428                         result = qtype_create (usymtab_supTypeEntry (ue));
429                       }
430                         
431                     cstring_free (cn);
432                   }
433                 /*@switchbreak@*/ break;
434               case SU_UNION:
435                 if (usymtab_existsUnionTag (cn))
436                   {
437                     
438                     result = qtype_create (uentry_getAbstractType
439                                            (usymtab_lookupUnionTag (cn)));
440                     cstring_free (cn);
441                   }
442                 else
443                   {
444                     uentryList fl;
445                     ctype ct;
446                     
447                     fl = convertuentryList (sn->structdecls);
448                     ct = ctype_createUnion (cstring_copy (cn), fl);
449
450                     /*
451                     ** If it was a forward declaration, this could add it to
452                     ** the table.  Need to check if it exists again...
453                     */
454
455                     
456                     
457                     if (usymtab_existsUnionTag (cn))
458                       {
459                         
460                         result = qtype_create (uentry_getAbstractType
461                                                (usymtab_lookupUnionTag (cn)));
462                       }
463                     else
464                       {
465                         fileloc loc = fileloc_fromTok (n->content.structorunion->tok);
466                         uentry ue = uentry_makeUnionTag (cn, ct, loc);
467
468                         result = qtype_create (usymtab_supTypeEntry (ue));
469                       }
470                         
471                     cstring_free (cn);
472                   }
473                 /*@switchbreak@*/ break;
474               BADDEFAULT
475               }
476             break;
477           }
478         case LTS_ENUM:
479           {
480             enumSpecNode e = n->content.enumspec;
481             enumNameList el;
482             cstring ename;
483             bool first = TRUE;
484             ctype ta;
485             ctype cet;
486
487             llassert (e != NULL);
488             el = convertEnumList (e->enums);
489
490             if (!ltoken_isUndefined (e->opttagid))      /* named enumerator */
491               {
492                 ename = cstring_copy (ltoken_getRawString (e->opttagid));
493               }
494             else
495               {
496                 ename = fakeTag ();
497               }
498
499             cet = ctype_createEnum (ename, el);
500             
501             if (usymtab_existsEnumTag (ename))
502               {
503                 ta = uentry_getAbstractType (usymtab_lookupEnumTag (ename));
504               }
505             else
506               { 
507                 fileloc loc = fileloc_fromTok (e->tok);
508                 uentry ue = uentry_makeEnumTag (ename, cet, loc);
509
510                 ta = usymtab_supTypeEntry (ue);
511               }
512
513             enumNameList_elements (el, en)
514               {
515                 uentry ue;
516                 fileloc loc;
517
518                 if (first)
519                   {
520                     ltokenList_reset (e->enums);
521                     first = FALSE;
522                   }
523                 else
524                   {
525                     ltokenList_advance (e->enums);
526                   }
527
528                 loc = fileloc_fromTok (ltokenList_current (e->enums));
529                 ue = uentry_makeSpecEnumConstant (en, cet, loc);
530
531                 /*
532                 ** Can't check name here, might not have
533                 ** type yet.  Will check in .lh file?
534                 */
535                 
536                 ue = usymtab_supGlobalEntryReturn (ue);
537                 
538                 if (context_inLCLLib ())
539                   {
540                     uentry_setDefined (ue, loc);
541                   }
542               } end_enumNameList_elements;
543             
544             result = qtype_create (ta);
545           }
546           break;
547         default:
548           {
549             llfatalbug (message ("convertLclTypeSpecNode: unknown lclTypeSpec kind: %d",
550                                  (int) n->kind));
551           }
552         }
553       
554       result = qtype_addQualList (result, n->quals);
555
556       if (n->pointers > 0)
557         {
558           qtype_adjustPointers (n->pointers, result);
559         }
560
561       return result;
562     }
563   else
564     {
565       llcontbug (cstring_makeLiteral ("convertLclTypeSpecNode: null"));
566       return qtype_unknown (); 
567     }
568   BADEXIT;
569
570
571 static /*@only@*/ multiVal
572   literalValue (ctype ct, ltoken lit)
573 {
574   cstring text = cstring_fromChars (lsymbol_toChars (ltoken_getText (lit)));
575   char first;
576
577   if (cstring_length (text) > 0)
578     {
579       first = cstring_firstChar (text);
580     }
581   else
582     {
583       return multiVal_unknown ();
584     }
585
586   
587   if /*@-usedef@*/ (first == '\"') /*@=usedef@*/
588     {
589       int len = cstring_length (text) - 2;
590       char *val = mstring_create (len);
591       
592       llassert (cstring_lastChar (text) == '\"');
593       strncpy (val, cstring_toCharsSafe (text) + 1, size_fromInt (len));
594       return (multiVal_makeString (cstring_fromCharsO (val)));
595     }
596
597   if (ctype_isDirectInt (ct) || ctype_isPointer (ct))
598     {
599       long val = 0;
600      
601       if (sscanf (cstring_toCharsSafe (text), "%ld", &val) == 1)
602         {
603           return multiVal_makeInt (val);
604         }
605     }
606
607   return multiVal_unknown ();
608 }
609
610
611 /*
612 ** declareConstant
613 **
614 ** unfortunately, because the abstract types are different, this
615 ** cannot be easily subsumed into declareVar.
616 */
617
618 void
619 doDeclareConstant (constDeclarationNode c, bool priv)
620 {
621   lclTypeSpecNode t;
622   ctype ctx;
623   qtype qt;
624   
625   if (c == (constDeclarationNode) 0)
626     {
627       return;
628     }
629
630   t = c->type;
631   qt = convertLclTypeSpecNode (t);
632
633   ctx = qtype_getType (qt);
634
635   initDeclNodeList_elements (c->decls, i)
636     {
637       ctype ct = convertTypeExpr (ctx, i->declarator->type);
638       cstring s = getVarName (i->declarator->type);
639
640       if (ctype_isFunction (ct))
641         {
642           fcnNode fcn = fcnNode_fromDeclarator (lclTypeSpecNode_copy (t), 
643                                                 declaratorNode_copy (i->declarator));
644
645           /* FALSE == unspecified function, only a declaration */
646
647           doDeclareFcn (fcn, typeId_invalid, priv, FALSE);
648           fcnNode_free (fcn);
649         }
650       else
651         {
652           uentry ue;
653           fileloc loc = fileloc_fromTok (i->declarator->id);
654
655           if (i->value != (termNode)0 &&
656               i->value->kind == TRM_LITERAL)
657             {
658               ue = uentry_makeConstantAux (s, ct, loc, priv, 
659                                            literalValue (ct, i->value->literal));
660             }
661           else
662             {
663               ue = uentry_makeConstantAux (s, ct, loc, priv, multiVal_unknown ());
664             }
665
666                   uentry_reflectQualifiers (ue, qtype_getQuals (qt));
667
668           
669           if (context_inLCLLib () && !priv)
670             {
671               uentry_setDefined (ue, loc);
672             }
673
674           usymtab_supGlobalEntry (ue);
675         }
676     } end_initDeclNodeList_elements;
677
678   qtype_free (qt);
679 }
680
681 static cstring
682 getVarName (/*@null@*/ typeExpr x)
683 {
684   cstring s = cstring_undefined;
685
686   if (x != (typeExpr) 0)
687     {
688       switch (x->kind)
689         {
690         case TEXPR_BASE:
691           s = ltoken_getRawString (x->content.base);
692           break;
693         case TEXPR_PTR:
694           s = getVarName (x->content.pointer);
695           break;
696         case TEXPR_ARRAY:
697           s = getVarName (x->content.array.elementtype);
698           break;
699         case TEXPR_FCN:
700           s = getVarName (x->content.function.returntype);
701           break;
702         default:
703           llfatalbug (message ("getVarName: unknown typeExprKind: %d", (int) x->kind));
704         }
705     }
706
707   return s;
708 }
709
710 void
711 doDeclareVar (varDeclarationNode v, bool priv)
712 {
713   lclTypeSpecNode t;
714   qtype c;
715
716   if (v == (varDeclarationNode) 0)
717     {
718       return;
719     }
720
721   t = v->type;
722   c = convertLclTypeSpecNode (t);
723
724   initDeclNodeList_elements (v->decls, i)
725     {
726       ctype ct = convertTypeExpr (qtype_getType (c), i->declarator->type);
727       cstring s = getVarName (i->declarator->type);
728
729       qtype_setType (c, ct);
730
731       if (ctype_isFunction (ct))
732         {
733           fcnNode fcn;
734
735                   
736           fcn = fcnNode_fromDeclarator (lclTypeSpecNode_copy (t), 
737                                         declaratorNode_copy (i->declarator));
738
739           /* FALSE == unspecified function, only a declaration */
740           declareFcnAux (fcn, qtype_unknown (), ct,
741                          typeId_invalid, priv, FALSE);
742           fcnNode_free (fcn);
743         }
744       else
745         {
746           fileloc loc = fileloc_fromTok (i->declarator->id);
747           uentry le = uentry_makeVariable (s, ct, loc, priv);
748           
749           uentry_reflectQualifiers (le, qtype_getQuals (c));
750           
751           if (uentry_isCheckedUnknown (le))
752             {
753               if (context_getFlag (FLG_IMPCHECKEDSTRICTSPECGLOBALS))
754                 {
755                   uentry_setCheckedStrict (le);
756                 }
757               else if (context_getFlag (FLG_IMPCHECKEDSPECGLOBALS))
758                 {
759                   uentry_setChecked (le);
760                 }
761               else if (context_getFlag (FLG_IMPCHECKMODSPECGLOBALS))
762                 {
763                   uentry_setCheckMod (le);
764                 }
765               else
766                 {
767                   ; /* okay */
768                 }
769             }
770
771           if (context_inLCLLib () && !priv)
772             {
773               uentry_setDefined (le, loc);
774             }
775
776           if (initDeclNode_isRedeclaration (i))
777             {
778               usymtab_replaceEntry (le);
779             }
780           else
781             {
782               le = usymtab_supEntrySrefReturn (le);
783             }
784         }
785     } end_initDeclNodeList_elements;
786
787   qtype_free (c);
788 }
789
790 static globSet
791 processGlob (/*@returned@*/ globSet globs, varDeclarationNode v)
792 {
793   if (v == (varDeclarationNode) 0)
794     {
795       return globs;
796     }
797
798   if (v->isSpecial)
799     {
800       globs = globSet_insert (globs, v->sref);
801     }
802   else
803     {
804       lclTypeSpecNode t = v->type;
805       qtype qt = convertLclTypeSpecNode (t);
806       ctype c = qtype_getType (qt);
807       cstring s;      
808
809       initDeclNodeList_elements (v->decls, i)
810         {
811           ctype ct;
812           uentry ue;
813           qualList quals = qtype_getQuals (qt);
814           
815           s = getVarName (i->declarator->type);
816           ue = usymtab_lookupGlobSafe (s);
817           
818           if (uentry_isInvalid (ue))
819             {
820               ; /* error already reported */ 
821             }
822           else
823             {
824               if (uentry_isPriv (ue))
825                 {
826                   globs = globSet_insert (globs, sRef_makeSpecState ());
827                 }
828               else
829                 {
830                   uentry ce = uentry_copy (ue);
831                   ctype lt = uentry_getType (ce);
832                   fileloc loc = fileloc_fromTok (i->declarator->id);
833                   
834                   ct = convertTypeExpr (c, i->declarator->type);
835                   
836                   if (!ctype_match (lt, ct))
837                     {
838                       (void) gentypeerror
839                         (lt, exprNode_undefined,
840                          ct, exprNode_undefined,
841                          message ("Global type mismatch %s (%t, %t)",
842                                   s, lt, ct), 
843                          loc);
844                     }
845                   
846                   uentry_reflectQualifiers (ce, quals);
847                   globs = globSet_insert (globs,
848                                           sRef_copy (uentry_getSref (ce)));
849                   fileloc_free (loc);
850                   uentry_free (ce);
851                 }
852             }
853         } end_initDeclNodeList_elements;
854
855       qtype_free (qt);
856     }
857
858   return globs;
859 }
860
861 static void
862 declareAbstractType (abstractNode n, bool priv)
863 {
864   cstring tn;
865   fileloc loc;
866   uentry ue;
867   usymId uid;
868   abstBodyNode ab;
869
870   if (n == (abstractNode) 0)
871     {
872       return;
873     }
874
875   
876   tn = ltoken_getRawString (n->name);
877
878   loc = fileloc_fromTok (n->tok);
879   
880   ue = uentry_makeDatatypeAux (tn, ctype_unknown, 
881                                ynm_fromBool (n->isMutable), YES, loc, priv);
882
883   if (n->isRefCounted)
884     {
885       uentry_setRefCounted (ue);
886     }
887
888   if (context_inLCLLib () && !priv)
889     {
890       uentry_setDefined (ue, loc);
891     }
892
893   uid = usymtab_supAbstractTypeEntry (ue, context_inLCLLib() && !priv);
894   
895
896   if (!priv && (ab = n->body) != (abstBodyNode) 0)
897     {
898       fcnNodeList ops = ab->fcns;
899
900       if (!fcnNodeList_isEmpty (ops))
901         {
902           fcnNodeList_elements (ops, i)
903           {
904             if (i->typespec == (lclTypeSpecNode) 0)
905               {
906                 cstring fname = ltoken_getRawString (i->name);
907
908                 if (usymtab_exists (fname))
909                   {
910                     uentry e = usymtab_lookup (fname);
911                     fileloc floc = fileloc_fromTok (i->declarator->id);
912
913                     if (uentry_isForward (e))
914                       {
915                         usymtab_supEntry  
916                           (uentry_makeTypeListFunction 
917                            (fname, typeIdSet_insert (uentry_accessType (e), uid), 
918                             floc));
919                       }
920                     else
921                       {
922                         usymtab_supEntry 
923                           (uentry_makeSpecFunction 
924                            (fname, uentry_getType (e),
925                             typeIdSet_insert (uentry_accessType (e), uid),
926                             globSet_undefined,
927                             sRefSet_undefined,
928                             floc));
929                         
930                         if (context_inLCLLib ())
931                           {
932                             llbuglit ("Jolly jeepers Wilma, it ain't dead after all!");
933                           }
934                       }
935                   }
936                 else
937                   {
938                     usymtab_supEntry 
939                       (uentry_makeForwardFunction (fname, uid, loc));
940                   }
941               }
942             else
943               {
944                 declareFcn (i, uid);
945               }
946           } end_fcnNodeList_elements;
947         }
948     }
949 }
950
951 static void
952   declareExposedType (exposedNode n, bool priv)
953 {
954   usymId uid;
955   qtype c;
956   cstring s;
957
958   
959   if (n == (exposedNode) 0)
960     {
961       return;
962     }
963
964   c = convertLclTypeSpecNode (n->type);
965
966   declaratorInvNodeList_elements (n->decls, i)
967   {
968     ctype realType = convertTypeExpr (qtype_getType (c), i->declarator->type);
969     fileloc loc = fileloc_fromTok (i->declarator->id);
970     uentry ue;
971
972     s = getVarName (i->declarator->type);
973
974     ue = uentry_makeDatatypeAux (s, realType, MAYBE, NO, 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     uid = 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 (usymId_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));
1581                   }
1582                 
1583                 else
1584                   {
1585                     sRef p = sRef_makeParam (i, ctype_unknown);
1586
1587                                     return (p);
1588                   }
1589               }
1590           }
1591         case TRM_APPLICATION:
1592           {
1593             nameNode nn = n->name;
1594
1595             if (nn != (nameNode) 0)
1596               {
1597                 if (nn->isOpId)
1598                   {
1599                     /* must we handle n->given ? skip for now */
1600
1601                     llfatalbug 
1602                       (message ("fixTermNode: expect non-empty nameNode: "
1603                                 "TRM_APPLICATION: %q",
1604                                 nameNode_unparse (nn)));
1605                   }
1606                 else
1607                   {
1608                     sRef sr;
1609
1610                     sr = processTermNode (nn->content.opform, n->args, f, cl);
1611                                     return (sr);
1612                   }
1613               }
1614             
1615             return sRef_undefined;
1616           }
1617         case TRM_UNCHANGEDALL:      
1618         case TRM_UNCHANGEDOTHERS:
1619         case TRM_SIZEOF:
1620         case TRM_QUANTIFIER:
1621           return sRef_undefined;
1622         }
1623     }
1624
1625   return sRef_undefined;
1626 }
1627
1628 static 
1629 /*@only@*/ sRefSet fixModifies (fcnNode f, uentryList cl)
1630 {
1631   static bool shownWarning = FALSE;
1632   modifyNode m = f->modify;
1633   sRefSet sl = sRefSet_new ();
1634
1635   if (m != (modifyNode) 0)
1636     {
1637       if (m->hasStoreRefList)
1638         {
1639           storeRefNodeList srefs = m->list;
1640
1641           storeRefNodeList_elements (srefs, i)
1642             {
1643               if (storeRefNode_isObj (i) || storeRefNode_isType (i))
1644                 {
1645                   if (!shownWarning)
1646                     {
1647                       fileloc loc = fileloc_fromTok (f->name);
1648                   
1649                       llmsg (message
1650                              ("%q: Warning: object and type modifications "
1651                               "not understood by LCLint",
1652                               fileloc_unparse (loc)));
1653                       fileloc_free (loc);
1654                       shownWarning = TRUE;
1655                     }
1656                 }
1657               else if (storeRefNode_isSpecial (i))
1658                 {
1659                   sl = sRefSet_insert (sl, i->content.ref);
1660                 }
1661               else if (storeRefNode_isTerm (i))
1662                 {
1663                   sRef s = fixTermNode (i->content.term, f, cl);
1664
1665                   if (sRef_isKnown (s)) 
1666                     {
1667                       sl = sRefSet_insert (sl, s);
1668                     }
1669                 }
1670               else
1671                 {
1672                   BADEXIT;
1673                 }
1674             } end_storeRefNodeList_elements;
1675           
1676         }
1677     }
1678
1679   return sl;
1680 }
1681
1682 static /*@only@*/ cstring
1683 paramNode_name (paramNode x)
1684 {
1685   return (typeExpr_name (x->paramdecl));
1686 }
1687
1688 static /*@only@*/ uentry
1689 paramNode_toUentry (paramNode p)
1690 {
1691   if (p != (paramNode) 0)
1692     {
1693       if (p->kind == PELIPSIS)
1694         {
1695           return uentry_makeElipsisMarker ();
1696         }
1697       else
1698         {
1699           qtype ct = convertLclTypeSpecNode (p->type);
1700           ctype cr = convertTypeExpr (qtype_getType (ct), p->paramdecl);
1701           cstring pname = (p->paramdecl == (typeExpr)0) ? cstring_undefined 
1702                                                         : paramNode_name (p);
1703           uentry ue = uentry_makeVariableParam (pname, cr);
1704
1705           uentry_reflectQualifiers (ue, qtype_getQuals (ct));
1706           qtype_free (ct);
1707           return (ue);
1708         }
1709     }
1710   else
1711     {
1712       llcontbuglit ("paramNode_toUentry: NULL");
1713       return uentry_undefined;
1714     }
1715   BADEXIT;
1716 }
1717
1718 static uentryList
1719   paramNodeList_toUentryList (paramNodeList p)
1720 {
1721   uentryList cl = uentryList_new ();
1722
1723   if (paramNodeList_isNull (p)) return (cl);
1724
1725   paramNodeList_elements (p, current)
1726     {
1727       cl = uentryList_add (cl, paramNode_toUentry (current));
1728     } end_paramNodeList_elements;
1729
1730   return cl;
1731 }
1732
1733
This page took 0.186707 seconds and 5 git commands to generate.