]> andersk Git - splint.git/blob - src/clabstract.c
Improved tracking of state change locations. Added +showdeephistory
[splint.git] / src / clabstract.c
1 /*
2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2002 University of Virginia,
4 **         Massachusetts Institute of Technology
5 **
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
10 ** 
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 ** General Public License for more details.
15 ** 
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
19 **
20 ** For information on splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
23 */
24 /*
25 ** clabstract.c
26 **
27 ** ASTs for C grammar
28 **
29 */
30
31 # include "splintMacros.nf"
32 # include "llbasic.h"
33 # include "cgrammar.h"
34 # include "usymtab_interface.h"
35
36 # include "structNames.h"
37 # include "nameChecks.h"
38
39 # ifdef SANITIZER
40 # include "sgrammar_tokens.h"
41 # else
42 # include "cgrammar_tokens.h"
43 # endif
44
45 /*
46 ** Lots of variables are needed because of interactions with the
47 ** parser.  This is easier than restructuring the grammar so the
48 ** right values are available in the right place.
49 */
50
51 /*drl*/
52 static /*@only@*/ constraintList implicitFcnConstraints = NULL;
53
54 static void clabstract_prepareFunction (uentry p_e) /*@modifies p_e@*/ ;
55 static bool fcnNoGlobals = FALSE;
56 static void processVariable (/*@temp@*/ idDecl p_t) /*@modifies internalState@*/ ;
57
58 static bool s_processingVars = FALSE;
59 static bool s_processingParams = FALSE;
60 static bool s_processingGlobals = FALSE;
61 static bool s_processingTypedef = FALSE;
62 static bool s_processingIterVars = FALSE;
63 static /*@only@*/ qtype processingType = qtype_undefined;
64 static uentry currentIter = uentry_undefined;
65 static /*@dependent@*/ uentryList saveParamList;  /* for old style functions */
66 static /*@owned@*/ uentry saveFunction = uentry_undefined;
67 static int saveIterParamNo;
68 static idDecl fixStructDecl (/*@returned@*/ idDecl p_d);
69 static void checkTypeDecl (uentry p_e, ctype p_rep);
70 static /*@dependent@*/ fileloc saveStoreLoc = fileloc_undefined;
71 static storageClassCode storageClass = SCNONE;
72 static void declareEnumList (/*@temp@*/ enumNameList p_el, ctype p_c, fileloc p_loc);
73 static void resetGlobals (void);
74 static /*@null@*/ qual specialFunctionCode;
75 static bool argsUsed = FALSE;
76
77 extern void clabstract_initMod () 
78 {
79   specialFunctionCode = qual_createUnknown ();
80   DPRINTF (("Initialized: %s", qual_unparse (specialFunctionCode)));
81 }
82
83 static bool hasSpecialCode (void)
84 {
85   return (!qual_isUnknown (specialFunctionCode));
86 }
87
88 extern void setArgsUsed (void)
89 {
90   if (argsUsed)
91     {
92       voptgenerror
93         (FLG_SYNTAX,
94          cstring_makeLiteral ("Multiple ARGSUSED comments for one function"),
95          g_currentloc);
96     }
97
98   argsUsed = TRUE;
99 }
100
101 static void reflectArgsUsed (uentry ue)
102 {
103   if (argsUsed)
104     {
105       if (uentry_isFunction (ue))
106         {
107           uentryList params = uentry_getParams (ue);
108
109           uentryList_elements (params, el)
110             {
111               uentry_setUsed (el, fileloc_undefined);
112             } end_uentryList_elements ;
113         }
114
115       argsUsed = FALSE;
116     }
117 }
118               
119 extern void setSpecialFunction (qual qu)
120 {
121   if (!qual_isUnknown (specialFunctionCode))
122     {
123       voptgenerror (FLG_SYNTAX,
124                     message ("Multiple special function codes: %s, %s "
125                              "(first code is ignored)",
126                              qual_unparse (specialFunctionCode),
127                              qual_unparse (qu)),
128                     g_currentloc);
129     }
130
131   specialFunctionCode = qu;
132 }
133
134 static void reflectSpecialCode (uentry ue)
135 {
136   if (qual_isUnknown (specialFunctionCode)) {
137     ;
138   } else if (qual_isPrintfLike (specialFunctionCode)) {
139     uentry_setPrintfLike (ue);
140   } else if (qual_isScanfLike (specialFunctionCode)) {
141     uentry_setScanfLike (ue);
142   } else if (qual_isMessageLike (specialFunctionCode)) {
143     uentry_setMessageLike (ue);
144   } else {
145     BADBRANCH;
146   }
147
148   specialFunctionCode = qual_createUnknown ();
149 }
150
151 static void resetStorageClass (void)
152 {
153   qtype_free (processingType);
154   processingType = qtype_undefined;
155   storageClass = SCNONE;
156 }
157
158 static void reflectStorageClass (uentry u)
159 {
160   if (storageClass == SCSTATIC)
161     {
162       uentry_setStatic (u);
163     }
164   else if (storageClass == SCEXTERN)
165     {
166       uentry_setExtern (u);
167     }
168   else
169     {
170       ; /* no storage class */
171     }
172
173   }
174
175 void storeLoc ()
176 {
177   saveStoreLoc = g_currentloc;
178 }
179
180 void setFunctionNoGlobals (void)
181 {
182   fcnNoGlobals = TRUE;
183 }
184
185 static void reflectGlobalQualifiers (sRef sr, qualList quals)
186 {
187   DPRINTF (("Reflect global qualifiers: %s / %s", 
188             sRef_unparseFull (sr), qualList_unparse (quals)));
189
190   qualList_elements (quals, qel)
191     {
192       if (qual_isGlobalQual (qel)) /* undef, killed */
193         {
194           sstate oldstate = sRef_getDefState (sr);
195           sstate defstate = sstate_fromQual (qel);
196           
197           if ((oldstate == SS_UNDEFGLOB && defstate == SS_KILLED)
198               || (oldstate == SS_KILLED && defstate == SS_UNDEFGLOB))
199             {
200               defstate = SS_UNDEFKILLED;
201             }
202           else 
203             {
204               ; /* any errors? */
205             }
206           
207           sRef_setDefState (sr, defstate, fileloc_undefined);
208           DPRINTF (("State: %s", sRef_unparseFull (sr)));
209         }
210       else if (qual_isAllocQual (qel)) /* out, partial, reldef, etc. */
211         {
212           ctype realType = sRef_getType (sr);
213           sstate defstate = sstate_fromQual (qel);
214           
215           if (qual_isRelDef (qel))
216             {
217               ; /* okay anywhere */
218             }
219           else
220             {
221               if (!ctype_isAP (realType) 
222                   && !ctype_isSU (realType)
223                   && !ctype_isUnknown (realType)
224                   && !ctype_isAbstract (sRef_getType (sr)))
225                 {
226                   llerror 
227                     (FLG_SYNTAX, 
228                      message ("Qualifier %s used on non-pointer or struct: %q",
229                               qual_unparse (qel), sRef_unparse (sr)));
230                   
231                 }
232             }
233           
234           sRef_setDefState (sr, defstate, fileloc_undefined);
235         }
236       else if (qual_isNull (qel))
237         {
238           sRef_setNullState (sr, NS_POSNULL, fileloc_undefined);
239         }
240       else if (qual_isRelNull (qel))
241         {
242           sRef_setNullState (sr, NS_RELNULL, fileloc_undefined);
243         }
244       else if (qual_isNotNull (qel))
245         {
246           sRef_setNullState (sr, NS_MNOTNULL, fileloc_undefined);
247         }
248       else
249         {
250           if (qual_isCQual (qel))
251             {
252               ; /* okay */
253             }
254           else
255             {
256               llerror (FLG_SYNTAX,
257                        message ("Qualifier %s cannot be used in a globals list",
258                                 qual_unparse (qel)));
259             }
260         }
261     } end_qualList_elements;
262 }
263
264 sRef clabstract_createGlobal (sRef sr, qualList quals)
265 {
266   sRef res;
267
268   if (sRef_isValid (sr))
269     {
270       res = sRef_copy (sr);
271       DPRINTF (("Reflecting quals: %s / %s", sRef_unparse (sr), qualList_unparse (quals)));
272       reflectGlobalQualifiers (res, quals);
273       DPRINTF (("==> %s", sRef_unparseFull (res)));
274     }
275   else
276     {
277       res = sRef_undefined;
278     }
279
280   qualList_free (quals);
281   return res;
282 }
283
284 extern void declareCIter (cstring name, /*@owned@*/ uentryList params)
285 {
286   uentry ue;
287
288   ue = uentry_makeIter (name, 
289                         ctype_makeFunction (ctype_void, params), 
290                         fileloc_copy (g_currentloc));
291
292   usymtab_supEntry (uentry_makeEndIter (name, fileloc_copy (g_currentloc)));
293   ue = usymtab_supGlobalEntryReturn (ue);
294 }
295
296 extern void nextIterParam (void)
297 {
298   llassert (s_processingIterVars);
299   saveIterParamNo++;
300 }
301
302 extern int iterParamNo (void)
303 {
304   llassert (s_processingIterVars);
305   return saveIterParamNo;
306 }
307
308 /*
309 ** yucky hacks to put it in the right place
310 */
311
312 /*@only@*/ uentry 
313 makeCurrentParam (idDecl t)
314 {
315   uentry ue;
316
317   saveStoreLoc = fileloc_undefined;
318
319   /* param number unknown */
320
321   ue = uentry_makeParam (t, 0);
322   return ue;
323 }
324
325 ctype
326 declareUnnamedEnum (enumNameList el)
327 {
328   ctype ret = usymtab_enumEnumNameListType (el);
329   ctype rt;
330   uentry e;
331
332   if (ctype_isDefined (ret))
333     {
334       rt = ret;
335       e = uentry_makeEnumTagLoc (ctype_enumTag (rt), ret);
336
337       reflectStorageClass (e);
338       usymtab_supGlobalEntry (e);
339       
340       declareEnumList (el, ret, g_currentloc);    
341       enumNameList_free (el);
342     }
343   else
344     {
345       ctype ct = ctype_createEnum (fakeTag (), el);
346
347       e = uentry_makeEnumTagLoc (ctype_enumTag (ctype_realType (ct)), ct);
348       reflectStorageClass (e);
349
350       e = usymtab_supGlobalEntryReturn (e);
351       rt = uentry_getAbstractType (e);
352       declareEnumList (el, ct, g_currentloc);    
353     }
354   
355   return (rt);
356 }
357
358 ctype
359 declareEnum (cstring ename, enumNameList el)
360 {
361   ctype cet;
362   uentry e;
363
364   llassert (cstring_isDefined (ename));
365
366   cet = ctype_createEnum (ename, el);
367   e = uentry_makeEnumTagLoc (ename, cet);
368   reflectStorageClass (e);
369   e = usymtab_supGlobalEntryReturn (e);
370   cet = uentry_getType (e);
371   declareEnumList (el, cet, uentry_whereLast (e));    
372   return (uentry_getAbstractType (e));
373 }
374
375 static void
376 declareEnumList (enumNameList el, ctype c, fileloc loc)
377 {
378   bool boolnames = FALSE;
379   bool othernames = FALSE;
380
381   (void) context_getSaveLocation (); /* undefine it */
382
383   if (context_maybeSet (FLG_NUMENUMMEMBERS))
384     {
385       int maxnum = context_getValue (FLG_NUMENUMMEMBERS);
386       int num = enumNameList_size (el);
387
388       if (num > maxnum)
389         {
390           voptgenerror 
391             (FLG_NUMENUMMEMBERS,
392              message ("Enumerator %s declared with %d members (limit is set to %d)",
393                       ctype_unparse (c), num, maxnum),
394              loc);
395         }
396     }
397
398   enumNameList_elements (el, e)
399     {
400       uentry ue = usymtab_lookupExposeGlob (e);
401       ctype ct = uentry_getType (ue);
402
403       llassert (uentry_isEnumConstant (ue));
404
405       if (ctype_isUnknown (ct))
406         {
407           uentry_setType (ue, c);
408         }
409       else
410         {
411           if (cstring_equal (e, context_getFalseName ())
412               || cstring_equal (e, context_getTrueName ()))
413             {
414               if (othernames) 
415                 {
416                   if (optgenerror 
417                       (FLG_INCONDEFS,
418                        message ("Enumerator mixes boolean name (%s) with "
419                                 "non-boolean names",
420                                 e),
421                        uentry_whereLast (ue)))
422                     {
423                       ;
424                     }
425                 }
426               
427               boolnames = TRUE;
428               uentry_setType (ue, ctype_bool);
429               DPRINTF (("Set type: %s / %s",
430                         uentry_unparse (ue), ctype_unparse (ctype_bool)));
431             }
432           else 
433             {
434               if (boolnames) 
435                 {
436                   if (optgenerror 
437                       (FLG_INCONDEFS,
438                        message ("Enumerator mixes boolean names (%s, %s) with "
439                                 "non-boolean name: %s",
440                                 context_getTrueName (),
441                                 context_getFalseName (),
442                                 e),
443                        uentry_whereLast (ue)))
444                     {
445                       ;
446                     }
447                 }
448
449               othernames = TRUE;
450             }
451
452           if (!ctype_match (c, ct))
453             {
454               if (ctype_isDirectBool (ct))
455                 {
456                   if (cstring_equal (e, context_getFalseName ())
457                       || cstring_equal (e, context_getTrueName ()))
458                     {
459                       DPRINTF (("Here we are!"));
460                     }
461                   else
462                     {
463                       if (optgenerror 
464                           (FLG_INCONDEFS,
465                            message ("Enumerator member %s declared with "
466                                     "inconsistent type: %s",
467                                     e, ctype_unparse (c)),
468                            uentry_whereLast (ue)))
469                         {
470                           uentry_showWhereSpecifiedExtra 
471                             (ue, cstring_copy (ctype_unparse (ct)));
472                         }
473                     }
474                 }
475               else
476                 {
477                   if (optgenerror 
478                       (FLG_INCONDEFS,
479                        message ("Enumerator member %s declared with "
480                                 "inconsistent type: %s",
481                                 e, ctype_unparse (c)),
482                        uentry_whereLast (ue)))
483                     {
484                       uentry_showWhereSpecifiedExtra 
485                         (ue, cstring_copy (ctype_unparse (ct)));
486                     }
487                 }
488             }
489         }
490     } end_enumNameList_elements;
491 }
492
493 static /*@dependent@*/ uentryList currentParamList;
494
495 /*drl added 3-28-2002*/
496 /* this function takes a list of paramentar and generates a list
497    of constraints.
498 */
499
500 /* drl modified 10/23/2002
501
502 The current semantics are generated constraints of the form MaxSet(p) >= 0 and MaxRead(p) >= 0 for all pointers
503 unless the @out@ annotation has been applied to a parameter, then we only want to generate maxSet(p) > = 0
504 */
505
506 void  setImplictfcnConstraints (void)
507 {
508   uentryList params;
509   sRef s;
510   constraint c;
511   params = currentParamList;
512
513   if (constraintList_isDefined(implicitFcnConstraints) )
514     constraintList_free(implicitFcnConstraints);
515    
516   implicitFcnConstraints  = constraintList_makeNew();
517   
518   uentryList_elements (params, el)
519     {
520       DPRINTF((message("setImplictfcnConstraints doing: %s", uentry_unparse(el) ) ));
521       
522       s = uentry_getSref(el);
523       if (sRef_isReference (s) )
524         {
525           DPRINTF((message ("%s is a pointer", sRef_unparse(s) ) ));
526         }
527       else
528         {
529           DPRINTF((message ("%s is NOT a pointer", sRef_unparse(s) ) ));
530         }
531       /*drl 4/26/01
532         chagned this from MaxSet(s) == 0 to MaxSet(s) >= 0 */
533       c = constraint_makeSRefWriteSafeInt (s, 0);
534       
535       implicitFcnConstraints = constraintList_add(implicitFcnConstraints , c);
536
537       /*drl 10/23/2002 added support for out*/
538       if (!uentry_isOut(el) )
539         {
540           c = constraint_makeSRefReadSafeInt (s, 0);
541       
542           implicitFcnConstraints = constraintList_add(implicitFcnConstraints , c);
543         }
544        
545       
546     }
547   end_uentryList_elements;
548   DPRINTF((message("implicitFcnConstraints has been set to %s\n",
549                    constraintList_print(implicitFcnConstraints) ) ));
550 }
551
552
553 /*@observer@*/ constraintList  getImplicitFcnConstraints (void)
554 {
555   return implicitFcnConstraints;
556 }
557
558 void setCurrentParams (/*@dependent@*/ uentryList ue)
559 {
560   currentParamList = ue;
561 }
562
563 void clearCurrentParams (void)
564 {
565     currentParamList = uentryList_undefined;
566 }
567
568 /*
569 ** requires: uentry_isFunction (e)
570 **           parameter names for current function are in currentParamList
571 */
572
573 static void enterFunctionParams (uentryList params)
574 {
575   int paramno = 0;
576
577   uentryList_elements (params, current)
578     {
579       if (uentry_hasName (current)) 
580         {
581           uentry_setParamNo (current, paramno);
582           usymtab_supEntry (uentry_copy (current));
583         }
584       
585       paramno++;
586     } end_uentryList_elements; 
587 }
588  
589
590 extern void enterParamsTemp (void)
591 {
592   usymtab_enterScope ();
593   enterFunctionParams (currentParamList);
594 }
595
596 extern void exitParamsTemp (void)
597 {
598   usymtab_quietPlainExitScope ();
599 }
600
601 static /*@exposed@*/ uentry clabstract_globalDeclareFunction (idDecl tid) 
602 {
603   ctype deftype = idDecl_getCtype (tid);
604   ctype rettype;
605   uentry ue;
606   
607   DPRINTF (("Global function: %s", idDecl_unparse (tid)));
608
609   if (ctype_isFunction (deftype))
610     {
611       rettype = ctype_getReturnType (deftype);
612     }
613   else
614     {
615       rettype = ctype_unknown;
616     }
617
618   /*
619   ** check has been moved here...
620   */
621
622   if (ctype_isFunction (idDecl_getCtype (tid)))
623     {
624       ue = uentry_makeIdFunction (tid);
625       reflectSpecialCode (ue);
626       reflectArgsUsed (ue);
627       reflectStorageClass (ue);
628       uentry_checkParams (ue);
629       
630       DPRINTF (("Supercede function: %s", uentry_unparseFull (ue)));
631       
632       ue = usymtab_supGlobalEntryReturn (ue);
633       DPRINTF (("After supercede function: %s", uentry_unparseFull (ue)));
634       
635       DPRINTF (("Enter function: %s", uentry_unparseFull (ue)));
636       context_enterFunction (ue);
637       enterFunctionParams (uentry_getParams (ue));
638       
639       resetStorageClass ();
640       DPRINTF (("Function: %s", uentry_unparseFull (ue)));
641       return (ue);
642     }
643   else
644     {    
645       llparseerror (message ("Non-function declaration: %q",
646                              idDecl_unparse (tid)));
647       return (uentry_undefined);
648     }
649 }
650
651 /*
652 ** for now, no type checking
653 ** (must check later though!)
654 */
655
656 static /*@only@*/ uentry globalDeclareOldStyleFunction (idDecl tid)
657 {
658   uentry ue;
659
660   /*
661   ** check has been moved here...
662   */
663
664   if (cstring_equalLit (idDecl_observeId (tid), "main"))
665     {
666       context_setFlagTemp (FLG_MAINTYPE, FALSE);
667     }
668
669   ue = uentry_makeIdFunction (tid);
670   reflectStorageClass (ue);
671   reflectSpecialCode (ue);
672   reflectArgsUsed (ue);
673   uentry_setDefined (ue, g_currentloc);
674   uentry_checkParams (ue);
675   resetStorageClass ();
676
677   /* context_enterOldStyleScope (); */
678
679   return (ue);
680 }
681
682 static void oldStyleDeclareFunction (/*@only@*/ uentry e)
683 {
684   uentryList params = saveParamList;
685   ctype rt = uentry_getType (e);
686
687   llassert (ctype_isFunction (rt));
688
689   if (uentry_hasStateClauseList (e) 
690       || uentry_hasConditions (e))
691     {
692       llfatalerror (message ("%q: Old-style function declaration uses a clause (rewrite with function parameters): %q",
693                              fileloc_unparse (g_currentloc), uentry_unparse (e)));
694     }
695
696   e = usymtab_supGlobalEntryReturn (e);
697
698   context_enterFunction (e);
699   enterFunctionParams (params);
700   saveParamList = uentryList_undefined;
701   resetStorageClass ();
702 }
703
704 static void oldStyleCompleteFunction (/*@only@*/ uentry e)
705 {
706   uentryList params = saveParamList;
707   ctype rt = uentry_getType (e);
708
709   llassert (ctype_isFunction (rt));
710
711   if (uentry_hasStateClauseList (e) 
712       || uentry_hasConditions (e))
713     {
714       llfatalerror (message ("%q: Old-style function declaration uses a clause (rewrite with function parameters): %q",
715                              fileloc_unparse (g_currentloc), uentry_unparse (e)));
716     }
717
718   e = usymtab_supGlobalEntryReturn (e);
719
720   context_completeOldStyleFunction (e);
721   enterFunctionParams (params);
722   saveParamList = uentryList_undefined;
723   resetStorageClass ();
724 }
725
726 void clabstract_declareFunction (idDecl tid) /*@globals undef saveFunction; @*/
727 {
728   uentry ue;
729
730   DPRINTF (("Declare function: %s", idDecl_unparse (tid)));
731   
732   if (ctype_isUnknown (idDecl_getCtype (tid)))
733     {
734       /*
735       ** No type, its really a plain name (int) declaration
736       */
737
738       voptgenerror (FLG_IMPTYPE,
739                     message ("No type before declaration name (implicit int type): %q",
740                              idDecl_unparse (tid)),
741                     g_currentloc);
742       tid = idDecl_replaceCtype (tid, ctype_int);
743       processVariable (tid);
744       saveFunction = uentry_undefined;
745     }
746   else
747     {
748       if (s_processingParams)
749         {
750           ue = globalDeclareOldStyleFunction (tid);
751           saveFunction = ue;
752           DPRINTF (("Set save function: %s", uentry_unparseFull (ue)));
753         }
754       else
755         {
756           saveFunction = uentry_undefined;
757           
758           if (context_inRealFunction ())
759             {
760               ue = uentry_makeVariableLoc (idDecl_observeId (tid), ctype_unknown);
761               
762               llparseerror (message ("Function declared inside function: %q",
763                                      idDecl_unparse (tid)));
764               
765               context_quietExitFunction ();
766               ue = usymtab_supEntryReturn (ue);
767             }
768           else
769             {
770               if (context_inInnerScope ())
771                 {
772                   llparseerror (message ("Declaration in inner context: %q",
773                                          idDecl_unparse (tid)));
774                   
775                   sRef_setGlobalScope ();
776                   ue = uentry_makeVariableLoc (idDecl_observeId (tid), 
777                                                ctype_unknown);
778                   ue = usymtab_supGlobalEntryReturn (ue);
779                   sRef_clearGlobalScope ();
780                 }
781               else
782                 {
783                   ue = clabstract_globalDeclareFunction (tid);
784                 }
785             }
786           
787           resetGlobals ();
788         }
789
790       resetStorageClass ();
791     }
792
793   idDecl_free (tid);
794 }
795
796 void declareStaticFunction (idDecl tid) /*@globals undef saveFunction; @*/
797 {
798   uentry ue;
799
800   DPRINTF (("Declare static funciton: %s", idDecl_unparse (tid)));
801
802   if (s_processingParams)
803     {
804       ue = globalDeclareOldStyleFunction (tid);
805       saveFunction = ue;
806     }
807   else
808     {
809       saveFunction = uentry_undefined;
810
811       if (context_inRealFunction ())
812         {
813           ue = uentry_makeVariableLoc (idDecl_observeId (tid), ctype_unknown);
814
815           llparseerror (message ("Function declared inside function: %q",
816                                  idDecl_unparse (tid)));
817           
818           context_quietExitFunction ();
819           ue = usymtab_supEntryReturn (ue);
820         }
821       else
822         {
823           if (context_inInnerScope ())
824             {
825               llparseerror (message ("Declaration in inner context: %q",
826                                      idDecl_unparse (tid)));
827               
828               sRef_setGlobalScope ();
829               ue = uentry_makeVariableLoc (idDecl_observeId (tid), 
830                                            ctype_unknown);
831               ue = usymtab_supGlobalEntryReturn (ue);
832               sRef_clearGlobalScope ();
833             }
834           else
835             {
836               ctype deftype = idDecl_getCtype (tid);
837               ctype rettype;
838               
839               if (ctype_isFunction (deftype))
840                 {
841                   rettype = ctype_getReturnType (deftype);
842                 }
843               else
844                 {
845                   rettype = ctype_unknown;
846                 }
847               
848               /*
849               ** check has been moved here...
850               */
851               
852               if (ctype_isFunction (idDecl_getCtype (tid)))
853                 {
854                   ue = uentry_makeIdFunction (tid);
855                   reflectSpecialCode (ue);
856                   reflectArgsUsed (ue);
857                 }
858               else
859                 {    
860                   DPRINTF (("Here we are!"));
861                   llparseerror (message ("Inconsistent function declaration: %q",
862                                          idDecl_unparse (tid)));
863                   
864                   tid = idDecl_replaceCtype 
865                     (tid, ctype_makeFunction (ctype_unknown, uentryList_undefined));
866                   ue = uentry_makeIdFunction (tid);
867                 }
868               
869               reflectStorageClass (ue);
870               uentry_setStatic (ue);
871
872               uentry_checkParams (ue);
873         
874               DPRINTF (("Sub global entry: %s", uentry_unparse (ue)));
875               ue = usymtab_supGlobalEntryReturn (ue);
876
877               context_enterFunction (ue);
878               enterFunctionParams (uentry_getParams (ue));
879               resetStorageClass ();
880             }
881         }
882       
883       resetGlobals ();
884     }
885   
886   resetStorageClass ();
887   idDecl_free (tid);
888 }
889
890 void
891 checkTypeDecl (uentry e, ctype rep)
892 {
893   cstring n = uentry_getName (e);
894
895   DPRINTF (("Check type decl: %s", uentry_unparseFull (e)));
896
897   if (cstring_equal (context_getBoolName (), n))
898     {
899       ctype rrep = ctype_realType (rep);
900       
901       /*
902       ** for abstract enum types, we need to fix the enum members:
903       ** they should have the abstract type, not the rep type.
904       */
905       
906       if (ctype_isEnum (ctype_realType (rrep)))
907         {
908           enumNameList el = ctype_elist (rrep);
909           
910           enumNameList_elements (el, ye)
911             {
912               if (usymtab_existsGlob (ye))
913                 {
914                   uentry ue = usymtab_lookupSafe (ye);
915                   uentry_setType (ue, ctype_bool);
916                 }
917
918               if (cstring_equal (context_getTrueName (), ye)
919                   || cstring_equal (context_getFalseName (), ye))
920                 {
921                   ;
922                 }
923               else
924                 {
925                   vgenhinterror 
926                     (FLG_SYNTAX,
927                      message ("Member of boolean enumerated type definition "
928                               "does not match name set to represent TRUE "
929                               "or FALSE: %s",
930                               ye),
931                      message ("Use -boolfalse and -booltrue to set the "
932                               "name of false and true boolean values."),
933                      uentry_whereDefined (e));
934                 }
935             } end_enumNameList_elements;
936         }
937     }
938
939   if (usymtab_exists (n))
940     {
941       usymId llm = usymtab_getId (n);
942       uentry le  = usymtab_getTypeEntry (llm);
943
944       uentry_setDeclared (e, g_currentloc); 
945       uentry_setSref (e, sRef_makeGlobal (llm, uentry_getType (le), stateInfo_currentLoc ()));
946
947       DPRINTF (("Here we are: %s / %s",
948                 n, context_getBoolName ()));
949       
950       if (uentry_isAbstractDatatype (le))
951         {
952           ctype rrep = ctype_realType (rep);
953
954           DPRINTF (("Abstract type: %s", uentry_unparseFull (le)));
955
956           /*
957           ** for abstract enum types, we need to fix the enum members:
958           ** they should have the abstract type, not the rep type.
959           */
960
961           if (ctype_isEnum (ctype_realType (rrep)))
962             {
963               ctype at = uentry_getAbstractType (le);
964               enumNameList el = ctype_elist (rrep);
965
966               enumNameList_elements (el, ye)
967                 {
968                   if (usymtab_existsGlob (ye))
969                     {
970                       uentry ue = usymtab_lookupSafe (ye);
971
972                       llassert (uentry_isEitherConstant (ue));
973
974                       /* evans 2002-04-22 */
975                       if (ctype_isBool (uentry_getType (ue)))
976                         {
977                           /*
978                           ** If set using -booltrue or -boolfalse, don't change the type.
979                           */
980                         }
981                       else
982                         {
983                           llassertprint (ctype_match (uentry_getType (ue), rrep),
984                                          ("Bad enum: %s / %s",
985                                           uentry_unparse (ue),
986                                           ctype_unparse (rrep)));
987                           
988                           uentry_setType (ue, at);
989                         }
990                     }
991                 } end_enumNameList_elements;
992             }
993           
994           if (uentry_isMutableDatatype (le))
995             {
996               /* maybe more complicated if abstract and immutable ? */
997
998               if (!ctype_isRealPointer (rep) && !ctype_isRealAbstract (rep))
999                 {
1000                   voptgenerror 
1001                     (FLG_MUTREP,
1002                      message ("Mutable abstract type %s declared without pointer "
1003                               "indirection: %s (violates assignment semantics)",
1004                               n, ctype_unparse (rep)),
1005                      uentry_whereDefined (e));
1006                   
1007                   uentry_setMutable (e);
1008                 }
1009             }
1010         }
1011     }
1012   else
1013     {
1014       fileloc fl = uentry_whereDeclared (e);
1015
1016       if (context_getFlag (FLG_LIKELYBOOL)
1017           && !context_getFlag (FLG_BOOLINT))
1018         {
1019           if ((cstring_equalLit (n, "BOOL")
1020                || cstring_equalLit (n, "Bool")
1021                || cstring_equalLit (n, "bool")
1022                || cstring_equalLit (n, "boolean")
1023                || cstring_equalLit (n, "Boolean")
1024                || cstring_equalLit (n, "BOOLEAN"))
1025               && !(cstring_equal (n, context_getBoolName ())))
1026             {
1027               if (context_setBoolName ()) {
1028                 voptgenerror 
1029                   (FLG_LIKELYBOOL,
1030                    message ("Type %s is probably meant as a boolean type, but does "
1031                             "not match the boolean type name \"%s\".",
1032                             n,
1033                             context_getBoolName ()),
1034                    fl);
1035               } else
1036                 voptgenerror 
1037                   (FLG_LIKELYBOOL,
1038                    message ("Type %s is probably meant as a boolean type, "
1039                             "but the boolean type name is not set. "
1040                             "Use -booltype %s to set it.",
1041                             n,
1042                             n),
1043                    fl);
1044                 }
1045         }
1046
1047       if (!uentry_isStatic (e)
1048           && !ctype_isFunction (uentry_getType (e)) 
1049           && !fileloc_isLib (fl) 
1050           && !fileloc_isImport (fl)
1051           && fileloc_isHeader (fl))
1052         {
1053           voptgenerror (FLG_EXPORTTYPE,
1054                         message ("Type exported, but not specified: %s\n", n),
1055                         fl);
1056         }
1057     }
1058
1059   cstring_free (n);
1060 }
1061
1062 uentryList
1063 fixUentryList (idDeclList tl, qtype q)
1064 {
1065   uentryList f = uentryList_new ();
1066   
1067   idDeclList_elements (tl, i)
1068   {
1069     if (idDecl_isDefined (i))
1070       {
1071         uentry ue;
1072         uentry old;
1073         ctype rt;
1074
1075         (void) idDecl_fixBase (i, q);
1076
1077         /*
1078         ** implicit annotations 
1079         */
1080
1081         (void) fixStructDecl (i);
1082
1083         ue = uentry_makeIdVariable (i);
1084         rt = ctype_realType (uentry_getType (ue));
1085
1086         /*
1087         ** where is this here???
1088
1089         if (ctype_isArray (rt) || ctype_isSU (rt))
1090           {
1091             sRef_setAllocated (uentry_getSref (ue), uentry_whereDefined (ue));
1092           }
1093
1094         **
1095         */
1096
1097         if (uentry_isValid (old = uentryList_lookupField (f, uentry_rawName (ue))))
1098           {
1099             if (optgenerror (FLG_SYNTAX,
1100                              message ("Field name reused: %s", uentry_rawName (ue)),
1101                              uentry_whereDefined (ue)))
1102               {
1103                 llgenmsg (message ("Previous use of %s", uentry_rawName (ue)),
1104                           uentry_whereDefined (old));
1105               }
1106           }
1107         
1108         f = uentryList_add (f, ue);
1109       }
1110   } end_idDeclList_elements;
1111
1112   idDeclList_free (tl);
1113   return (f);
1114 }
1115
1116 /*
1117 ** This is a hack to support unnamed struct/union fields as done by
1118 ** Microsoft VC++.  It is not supported by the ANSI standard.  
1119 **
1120 ** The inner fields are added to the outer structure.  This is meaningful
1121 ** for nesting structs inside unions, but Splint does no related 
1122 ** checking.
1123 */
1124
1125 uentryList
1126 fixUnnamedDecl (qtype q)
1127 {
1128   ctype ct = ctype_realType (qtype_getType (q));
1129
1130   if (ctype_isStruct (ct) || ctype_isUnion (ct))
1131     {
1132       return uentryList_single (uentry_makeUnnamedVariable (ct));
1133     }
1134   else if (ctype_isEnum (ct))
1135     {
1136       /* evans 2002-02-05: nothing to do for unnamed enum lists */
1137       return uentryList_undefined;
1138     }
1139   else
1140     { 
1141       voptgenerror 
1142         (FLG_SYNTAX,
1143          message ("Type name in field declarations: %s", qtype_unparse (q)),
1144          g_currentloc);
1145     }
1146
1147   return uentryList_undefined;
1148 }
1149
1150 void setStorageClass (storageClassCode sc)
1151 {
1152   storageClass = sc;
1153 }
1154
1155 void
1156 setProcessingIterVars (uentry iter)
1157 {
1158   s_processingIterVars = TRUE;
1159   currentIter = iter;
1160   saveIterParamNo = 0;
1161 }
1162
1163 void
1164 setProcessingGlobalsList ()
1165 {
1166   s_processingGlobals = TRUE;
1167   fcnNoGlobals = FALSE;
1168 }
1169
1170 static bool ProcessingGlobMods = FALSE;
1171
1172 void
1173 setProcessingGlobMods ()
1174 {
1175   ProcessingGlobMods = TRUE;
1176 }
1177
1178 void
1179 clearProcessingGlobMods ()
1180 {
1181   ProcessingGlobMods = FALSE;
1182 }
1183
1184 bool
1185 isProcessingGlobMods ()
1186 {
1187   return (ProcessingGlobMods);
1188 }
1189
1190 static void resetGlobals (void)
1191 {
1192   s_processingGlobals = FALSE;
1193   fcnNoGlobals = FALSE;
1194 }
1195
1196 void
1197 unsetProcessingGlobals ()
1198 {
1199   s_processingGlobals = FALSE;
1200 }
1201
1202 void
1203 setProcessingVars (/*@only@*/ qtype q)
1204 {
1205   s_processingVars = TRUE;
1206   qtype_free (processingType);
1207   processingType = q;
1208 }
1209
1210 static void
1211 setGenericParamList (/*@dependent@*/ uentryList pm)
1212 {
1213   s_processingParams = TRUE;
1214   saveParamList = pm;
1215 }
1216
1217 void
1218 setProcessingTypedef (qtype q)
1219 {
1220   s_processingTypedef = TRUE;
1221
1222   qtype_free (processingType);
1223   processingType = q;
1224 }
1225
1226 void
1227 unsetProcessingVars ()
1228 {
1229   resetStorageClass ();
1230   s_processingVars = FALSE;
1231 }
1232
1233 void 
1234 oldStyleDoneParams ()
1235 {  
1236   if (s_processingParams)
1237     {
1238       if (uentry_isInvalid (saveFunction))
1239         {
1240           llbuglit ("unsetProcessingVars: no saved function\n");
1241         }
1242       else
1243         {
1244           ctype ct = ctype_getReturnType (uentry_getType (saveFunction));
1245           uentryList params = uentryList_copy (saveParamList);
1246           ctype ct2 = ctype_makeFunction (ct, params);
1247
1248           uentry_setType (saveFunction, ct2);
1249           s_processingParams = FALSE;
1250
1251           oldStyleCompleteFunction (saveFunction);
1252           saveFunction = uentry_undefined;
1253           resetGlobals ();
1254         }
1255     }
1256   else
1257     {
1258       /*
1259       ** If the paramlist used a type name, we could be here.
1260       */
1261
1262       llfatalerror (message ("%q: Old-style function parameter list uses a "
1263                              "type name.", fileloc_unparse (g_currentloc)));
1264     }
1265 }
1266
1267 void 
1268 checkDoneParams ()
1269 {
1270   if (uentry_isValid (saveFunction))
1271     {
1272       /*
1273       ** old style declaration
1274       */
1275
1276       ctype ct = ctype_getReturnType (uentry_getType (saveFunction));
1277       ctype ct2;
1278
1279       DPRINTF (("save function: %s", uentry_unparseFull (saveFunction)));
1280
1281       uentryList_elements (saveParamList, current)
1282         {
1283           uentry_setType (current, ctype_int); /* all params are ints */
1284         } end_uentryList_elements; 
1285
1286       ct2 = ctype_makeParamsFunction (ct, uentryList_copy (saveParamList));
1287       
1288       uentry_setType (saveFunction, ct2);
1289       s_processingParams = FALSE;
1290       
1291       oldStyleDeclareFunction (saveFunction);
1292       saveFunction = uentry_undefined;
1293     }
1294 }
1295
1296 void clabstract_declareType (/*@only@*/ exprNodeList decls, /*@only@*/ warnClause warn)
1297 {
1298   llassert (s_processingTypedef);
1299
1300   DPRINTF (("Declare type: %s", exprNodeList_unparse (decls)));
1301
1302   if (warnClause_isDefined (warn))
1303     {
1304       DPRINTF (("Has a warn clause!"));
1305       DPRINTF (("Warn: %s", warnClause_unparse (warn)));
1306
1307       exprNodeList_elements (decls, el)
1308         {
1309           uentry ue = exprNode_getUentry (el);
1310           cstring uname = uentry_getName (ue);
1311
1312           DPRINTF (("Entry: %s", exprNode_unparse (el)));
1313
1314           /*
1315           ** Need to lookup again to make sure we have the right one...
1316           */
1317
1318           ue = usymtab_lookupExposeGlob (uname);
1319
1320           llassert (uentry_isValid (ue));
1321           llassert (uentry_isDatatype (ue));
1322
1323           DPRINTF (("Warning for %s: %s",
1324                     uentry_unparse (ue), warnClause_unparse (warn)));
1325
1326           uentry_addWarning (ue, warnClause_copy (warn));
1327           DPRINTF (("After add warning: %s", uentry_unparseFull (ue)));
1328           cstring_free (uname);
1329         } end_exprNodeList_elements;
1330     }
1331
1332   warnClause_free (warn);
1333   exprNodeList_free (decls);
1334   unsetProcessingTypedef ();
1335 }
1336
1337 void
1338 unsetProcessingTypedef ()
1339 {
1340   s_processingTypedef = FALSE;
1341 }
1342
1343 void checkConstant (qtype t, idDecl id) 
1344 {
1345   uentry e;
1346   
1347   id = idDecl_fixBase (id, t);
1348   e = uentry_makeIdConstant (id);
1349   
1350   reflectStorageClass (e);
1351   resetStorageClass ();
1352
1353   DPRINTF (("Constant: %s", uentry_unparseFull (e)));
1354   usymtab_supGlobalEntry (e);
1355 }
1356
1357 void checkValueConstant (qtype t, idDecl id, exprNode e) 
1358 {
1359   uentry ue;
1360
1361   id = idDecl_fixBase (id, t);
1362   ue = uentry_makeIdConstant (id);
1363   reflectStorageClass (ue);
1364   resetStorageClass ();
1365
1366   if (exprNode_isDefined (e))
1367     {
1368       if (!exprNode_matchType (uentry_getType (ue), e))
1369         {
1370           (void) gentypeerror 
1371             (exprNode_getType (e), e,
1372              uentry_getType (ue), exprNode_undefined,
1373              message ("Constant %q initialized to type %t, expects %t: %s",
1374                       uentry_getName (ue),  
1375                       exprNode_getType (e), 
1376                       uentry_getType (ue),
1377                       exprNode_unparse (e)),
1378              exprNode_loc (e));
1379         }
1380       else
1381         {
1382           if (exprNode_hasValue (e))
1383             {
1384               uentry_mergeConstantValue (ue, multiVal_copy (exprNode_getValue (e)));
1385             }
1386           else
1387             {
1388               DPRINTF (("No value: %s", exprNode_unparse (e)));
1389             }
1390         }
1391     }
1392
1393   DPRINTF (("Constant value: %s", uentry_unparseFull (ue)));
1394   usymtab_supGlobalEntry (ue);
1395 }
1396
1397 static void processVariable (idDecl t)
1398 {
1399   uentry e;
1400   ctype ct;
1401   
1402   ct = ctype_realType (idDecl_getCtype (t));
1403   
1404   if (s_processingParams)
1405     {
1406       cstring id = idDecl_getName (t);
1407       int paramno = uentryList_lookupRealName (saveParamList, id);
1408       
1409       if (paramno >= 0)
1410         {
1411           uentry cparam = uentryList_getN (saveParamList, paramno);
1412           
1413           DPRINTF (("Processing param: %s", uentry_unparseFull (cparam)));
1414           uentry_setType (cparam, idDecl_getCtype (t));
1415           uentry_reflectQualifiers (cparam, idDecl_getQuals (t));
1416           uentry_setDeclaredOnly (cparam, context_getSaveLocation ());
1417           DPRINTF (("Processing param: %s", uentry_unparseFull (cparam)));
1418         }
1419       else
1420         {
1421           llfatalerrorLoc
1422             (message ("Old style declaration uses unlisted parameter: %s", 
1423                       id));
1424         }
1425     }
1426   else
1427     {
1428       fileloc loc;
1429       
1430       if (context_inIterDef ())
1431         {
1432           cstring pname = makeParam (idDecl_observeId (t));
1433           uentry p = usymtab_lookupSafe (pname);
1434           
1435           cstring_free (pname);
1436           
1437           if (uentry_isYield (p))
1438             {
1439               e = uentry_makeParam (t, sRef_getParam (uentry_getSref (p)));
1440               uentry_checkYieldParam (p, e);
1441               usymtab_supEntrySref (e);
1442               return;
1443             }
1444         }
1445       
1446       if ((hasSpecialCode () || argsUsed)
1447           && ctype_isFunction (idDecl_getCtype (t)))
1448         {
1449           e = uentry_makeIdFunction (t);
1450           reflectSpecialCode (e);
1451           reflectArgsUsed (e);
1452         }
1453       else
1454         {
1455           e = uentry_makeIdVariable (t);
1456         }
1457       
1458       loc = uentry_whereDeclared (e);
1459       
1460       /*
1461         if (context_inGlobalScope ())
1462         {
1463         uentry_checkParams was here!
1464         }
1465       */
1466       
1467       if (ctype_isFunction (uentry_getType (e)))
1468         {
1469           clabstract_prepareFunction (e);
1470         }
1471       
1472       DPRINTF (("Superceding... %s", uentry_unparseFull (e)));
1473       e = usymtab_supEntrySrefReturn (e);
1474       DPRINTF (("After superceding... %s", uentry_unparseFull (e)));      
1475       
1476       if (uentry_isExtern (e) && !context_inGlobalScope ())
1477         {
1478           voptgenerror 
1479             (FLG_NESTEDEXTERN,
1480              message ("Declaration using extern inside function scope: %q",
1481                       uentry_unparse (e)),
1482              g_currentloc);
1483           
1484           uentry_setDefined (e, fileloc_getExternal ());
1485           sRef_setDefined (uentry_getSref (e), fileloc_getExternal ());
1486         }
1487       
1488       if (uentry_isFunction (e))
1489         {
1490           if (!context_inXHFile ())
1491             {
1492               checkParamNames (e);
1493             }
1494         }
1495       
1496       if (uentry_isVar (e) && uentry_isCheckedUnknown (e))
1497         {
1498           sRef sr = uentry_getSref (e);
1499           
1500           if (sRef_isLocalVar (sr))
1501             {
1502               if (context_getFlag (FLG_IMPCHECKMODINTERNALS))
1503                 {
1504                   uentry_setCheckMod (e);
1505                 }
1506               else
1507                 {
1508                   uentry_setUnchecked (e);
1509                 }
1510             }
1511           else if (sRef_isFileStatic (sr))
1512             {
1513               if (context_getFlag (FLG_IMPCHECKEDSTRICTSTATICS))
1514                 {
1515                   uentry_setCheckedStrict (e);
1516                 }
1517               else if (context_getFlag (FLG_IMPCHECKEDSTATICS))
1518                 {
1519                   uentry_setChecked (e);
1520                 }
1521               else if (context_getFlag (FLG_IMPCHECKMODSTATICS))
1522                 {
1523                   uentry_setCheckMod (e);
1524                 }
1525               else
1526                 {
1527                   ;
1528                 }
1529             }
1530           else /* real global */
1531             {
1532               llassert (sRef_isRealGlobal (sr));
1533               
1534               if (context_getFlag (FLG_IMPCHECKEDSTRICTGLOBALS))
1535                 {
1536                   uentry_setCheckedStrict (e);
1537                 }
1538               else if (context_getFlag (FLG_IMPCHECKEDGLOBALS))
1539                 {
1540                   uentry_setChecked (e);
1541                 }
1542               else if (context_getFlag (FLG_IMPCHECKMODGLOBALS))
1543                 {
1544                   uentry_setCheckMod (e);
1545                 }
1546               else
1547                 {
1548                   ;
1549                 }
1550             }
1551         }
1552     }
1553 }
1554
1555 void processNamedDecl (idDecl t)
1556 {
1557   if (qtype_isUndefined (processingType))
1558     {
1559       processingType = qtype_create (ctype_int);
1560       t = idDecl_fixBase (t, processingType);
1561
1562       voptgenerror (FLG_IMPTYPE,
1563                     message ("No type before declaration name (implicit int type): %q",
1564                              idDecl_unparse (t)),
1565                     g_currentloc);
1566     }
1567   else
1568     {
1569       t = idDecl_fixBase (t, processingType);
1570     }
1571
1572   DPRINTF (("Declare: %s", idDecl_unparse (t)));
1573   
1574   if (s_processingGlobals)
1575     {
1576       cstring id = idDecl_getName (t);
1577       uentry ue = usymtab_lookupSafe (id);
1578       
1579       if (!uentry_isValid (ue))
1580         {
1581           llerror (FLG_UNRECOG,
1582                    message ("Variable used in globals list is undeclared: %s", id));
1583         }
1584       else
1585         {
1586           if (!ctype_match (uentry_getType (ue), idDecl_getCtype (t)))
1587             {
1588               voptgenerror 
1589                 (FLG_INCONDEFS,
1590                  message ("Variable %s used in globals list declared %s, "
1591                           "but listed as %s", 
1592                           id, ctype_unparse (uentry_getType (ue)), 
1593                           ctype_unparse (idDecl_getCtype (t))),
1594                  g_currentloc);
1595             }
1596           else
1597             {
1598               sRef sr = sRef_copy (uentry_getSref (ue));
1599               reflectGlobalQualifiers (sr, idDecl_getQuals (t));
1600             }
1601         }
1602     }
1603   else if (s_processingVars)
1604     {
1605       processVariable (t);
1606     }
1607   else if (s_processingTypedef)
1608     {
1609       ctype ct = idDecl_getCtype (t);
1610       uentry e;
1611       
1612       DPRINTF (("Processing typedef: %s", ctype_unparse (ct)));
1613       
1614       e = uentry_makeIdDatatype (t);
1615
1616       if (cstring_equal (idDecl_getName (t), context_getBoolName ())) {
1617         ctype rt = ctype_realType (ct);
1618         
1619         if (ctype_isEnum (rt)) {
1620           ;
1621         } else {
1622           if (!(ctype_isInt (rt)
1623                 || ctype_isUnknown (rt)
1624                 || ctype_isChar (rt))) {
1625             (void) llgenerror
1626               (FLG_BOOLTYPE, 
1627                message ("Boolean type %s defined using non-standard type %s (integral, char or enum type expected)",
1628                         context_getBoolName (),
1629                         ctype_unparse (ct)),
1630                uentry_whereLast (e));
1631           }
1632           
1633           ct = ctype_bool;
1634           uentry_setType (e, ct);
1635         }
1636       }
1637
1638       reflectStorageClass (e);
1639       checkTypeDecl (e, ct);
1640       
1641       e = usymtab_supReturnTypeEntry (e);
1642     }
1643   else
1644     {
1645       llparseerror (message ("Suspect missing struct or union keyword: %q",
1646                              idDecl_unparse (t)));
1647     }
1648
1649   }
1650
1651 /*
1652 ** moved from grammar
1653 */
1654
1655 static idDecl fixStructDecl (/*@returned@*/ idDecl d)
1656 {
1657   if (ctype_isVisiblySharable (idDecl_getCtype (d)) 
1658       && context_getFlag (FLG_STRUCTIMPONLY))
1659     {
1660       if (!qualList_hasAliasQualifier (idDecl_getQuals (d)))
1661         {
1662           if (qualList_hasExposureQualifier (idDecl_getQuals (d)))
1663             {
1664               idDecl_addQual (d, qual_createDependent ());
1665             }
1666           else
1667             {
1668               idDecl_addQual (d, qual_createImpOnly ());
1669             }
1670         }
1671     }
1672
1673   return d;
1674 }
1675
1676 ctype
1677 declareUnnamedStruct (/*@only@*/ uentryList f)
1678 {
1679   DPRINTF (("Unnamed struct: %s", uentryList_unparse (f)));
1680
1681   if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
1682     {
1683       int num = uentryList_size (f);
1684       int max = context_getValue (FLG_NUMSTRUCTFIELDS);
1685
1686       if (num > max)
1687         {
1688           voptgenerror 
1689             (FLG_NUMSTRUCTFIELDS,
1690              message ("Structure declared with %d fields "
1691                       "(limit is set to %d)",
1692                       num, max),
1693              g_currentloc);
1694         }
1695     }
1696
1697   return (ctype_createUnnamedStruct (f));
1698 }
1699
1700 ctype
1701 declareUnnamedUnion (/*@only@*/ uentryList f)
1702 {
1703   DPRINTF (("Unnamed union: %s", uentryList_unparse (f)));
1704
1705   if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
1706     {
1707       int num = uentryList_size (f);
1708       int max = context_getValue (FLG_NUMSTRUCTFIELDS);
1709
1710       if (num > max)
1711         {
1712           voptgenerror 
1713             (FLG_NUMSTRUCTFIELDS,
1714              message ("Union declared with %d fields "
1715                       "(limit is set to %d)",
1716                       num, max),
1717              g_currentloc);
1718         }
1719     }
1720
1721   return (ctype_createUnnamedUnion (f));
1722 }
1723
1724 ctype declareStruct (cstring id, /*@only@*/ uentryList f)
1725 {
1726   ctype ct; 
1727   uentry ue;
1728   int num = uentryList_size (f);
1729
1730   DPRINTF (("Declare struct: %s / %s [%d]", id, uentryList_unparse (f),
1731             uentryList_size (f)));
1732
1733   ct = ctype_createStruct (cstring_copy (id), f);
1734
1735   DPRINTF (("Ctype: %s", ctype_unparse (ct)));
1736
1737   ue = uentry_makeStructTagLoc (id, ct);
1738
1739   DPRINTF (("ue: %s", uentry_unparseFull (ue)));
1740
1741   if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
1742     {
1743       int max = context_getValue (FLG_NUMSTRUCTFIELDS);
1744
1745       if (num > max)
1746         {
1747           voptgenerror 
1748             (FLG_NUMSTRUCTFIELDS,
1749              message ("Structure %q declared with %d fields "
1750                       "(limit is set to %d)",
1751                       uentry_getName (ue), num, max),
1752              uentry_whereLast (ue));
1753         }
1754     }
1755
1756   return (usymtab_supTypeEntry (ue));
1757 }
1758
1759 ctype declareUnion (cstring id, uentryList f)
1760 {
1761   ctype ct; 
1762   uentry ue;
1763   int num = uentryList_size (f);
1764
1765   ct = ctype_createUnion (cstring_copy (id), f);
1766   ue = uentry_makeUnionTagLoc (id, ct);
1767
1768   if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
1769     {
1770       int max = context_getValue (FLG_NUMSTRUCTFIELDS);
1771
1772       if (num > max)
1773         {
1774           voptgenerror 
1775             (FLG_NUMSTRUCTFIELDS,
1776              message ("Union %q declared with %d fields "
1777                       "(limit is set to %d)",
1778                       uentry_getName (ue), num, max),
1779              uentry_whereLast (ue));
1780         }
1781     }
1782
1783   return (usymtab_supTypeEntry (ue));
1784 }
1785
1786 ctype handleStruct (/*@only@*/ cstring id)
1787 {
1788   if (usymtab_existsStructTag (id))
1789     {
1790       ctype ct = uentry_getAbstractType (usymtab_lookupStructTag (id));
1791
1792       cstring_free (id);
1793       return ct;
1794     }
1795   else
1796     {
1797       return (ctype_createForwardStruct (id));
1798     }
1799 }
1800
1801 ctype handleUnion (/*@only@*/ cstring id)
1802 {
1803   if (usymtab_existsUnionTag (id))
1804     {
1805       ctype ret = uentry_getAbstractType (usymtab_lookupUnionTag (id));
1806       cstring_free (id);
1807       return (ret);
1808     }
1809   else
1810     {
1811       return (ctype_createForwardUnion (id));
1812     }
1813 }
1814
1815 ctype
1816 handleEnum (cstring id)
1817 {
1818   if (usymtab_existsEnumTag (id))
1819     {
1820       ctype ret = uentry_getAbstractType (usymtab_lookupEnumTag (id));
1821       cstring_free (id);
1822       return ret;
1823     }
1824   else
1825     {
1826       return (ctype_createForwardEnum (id));
1827     }
1828 }
1829
1830 bool processingIterVars (void) 
1831
1832   return s_processingIterVars; 
1833 }
1834
1835 uentry getCurrentIter (void) 
1836 {
1837   return currentIter; 
1838 }
1839
1840 static bool flipOldStyle = FALSE;
1841 static bool flipNewStyle = TRUE;
1842
1843 void setFlipOldStyle ()          { flipOldStyle = TRUE; }
1844 bool isFlipOldStyle ()           { return flipOldStyle; }
1845 bool isNewStyle ()               { return flipNewStyle; }
1846 void setNewStyle ()              { flipNewStyle = TRUE; }
1847
1848 /*@dependent@*/ uentryList handleParamIdList (/*@dependent@*/ uentryList params)
1849 {  
1850   int paramno = 0;
1851
1852   /*
1853   ** this is a really YUCKY hack to handle old style
1854   ** declarations.
1855   */
1856   
1857   voptgenerror (FLG_OLDSTYLE,
1858                 cstring_makeLiteral ("Old style function declaration"),
1859                 g_currentloc); 
1860
1861   DPRINTF (("Handle old style params: %s", uentryList_unparseFull (params)));
1862
1863   uentryList_elements (params, current)
1864     {
1865       uentry_setParam (current);
1866       uentry_setSref (current, sRef_makeParam 
1867                       (paramno, ctype_unknown, 
1868                        stateInfo_makeLoc (uentry_whereLast (current), SA_DECLARED)));
1869       paramno++;
1870     } end_uentryList_elements;
1871
1872   setGenericParamList (params);
1873   cscannerHelp_setExpectingTypeName ();
1874
1875   return params;
1876 }
1877
1878 /*@dependent@*/ uentryList handleParamTypeList (/*@returned@*/ uentryList params)
1879 {
1880   if (flipOldStyle)
1881     {
1882       uentryList_fixMissingNames (params);
1883
1884       voptgenerror (FLG_OLDSTYLE, 
1885                     cstring_makeLiteral ("Old style function declaration."), 
1886                     g_currentloc); 
1887       
1888       setGenericParamList (params);
1889       flipOldStyle = FALSE;
1890       cscannerHelp_setExpectingTypeName ();
1891     }
1892  
1893   return (params); 
1894 }
1895
1896 void
1897 doVaDcl ()
1898 {
1899   ctype c = ctype_unknown;
1900   cstring id = cstring_makeLiteral ("va_alist");
1901   uentry e;
1902
1903   if (s_processingParams)
1904     {
1905       int i = uentryList_lookupRealName (saveParamList, id);
1906       
1907       if (i >= 0)
1908         {
1909           fileloc loc = context_getSaveLocation ();
1910           e = uentry_makeVariableSrefParam 
1911             (id, c, loc, 
1912              sRef_makeParam (i, c, stateInfo_makeLoc (loc, SA_DECLARED)));
1913         }
1914       else
1915         {
1916           e = uentry_undefined; /* suppress gcc message */
1917           llfatalerrorLoc (cstring_makeLiteral ("va_dcl used without va_alist"));
1918         }
1919     }
1920   else
1921     {    
1922       llerror (FLG_SYNTAX, cstring_makeLiteral ("va_dcl used outside of function declaration"));
1923       e = uentry_makeVariableLoc (id, c);
1924     }
1925
1926   cstring_free (id);
1927   uentry_setUsed (e, g_currentloc);  
1928   usymtab_supEntrySref (e);
1929 }
1930
1931 /*@exposed@*/ sRef modListPointer (/*@exposed@*/ sRef s)
1932 {
1933   ctype ct = sRef_getType (s);
1934   ctype rt = ctype_realType (ct);
1935   
1936   if (ctype_isAP (rt))
1937     {
1938       if (context_inHeader () && ctype_isAbstract (ct))
1939         {
1940           voptgenerror 
1941             (FLG_ABSTRACT,
1942              message
1943              ("Modifies clause in header file dereferences abstract "
1944               "type %s (interface modifies clause should not depend "
1945               "on or expose type representation): %q",
1946               ctype_unparse (ct),
1947               sRef_unparse (s)),
1948              g_currentloc);
1949         }
1950
1951       return (sRef_constructPointer (s));
1952     }
1953   else
1954     {
1955       if (ctype_isKnown (rt))
1956         {
1957           voptgenerror 
1958             (FLG_TYPE,
1959              message ("Implementation modifies clause dereferences non-pointer (type %s): %q",
1960                       ctype_unparse (rt),
1961                       sRef_unparse (s)),
1962              g_currentloc);
1963         }
1964
1965       return s;
1966     }
1967 }
1968
1969 /*@exposed@*/ sRef modListFieldAccess (sRef s, cstring f)
1970 {
1971   ctype ct = sRef_getType (s);
1972   ctype rt = ctype_realType (ct);
1973   
1974   if (ctype_isStructorUnion (rt))
1975     {
1976       uentry tf = uentryList_lookupField (ctype_getFields (rt), f);
1977       
1978       if (uentry_isUndefined (tf))
1979         {
1980           voptgenerror (FLG_TYPE,
1981                         message ("Modifies list accesses non-existent "
1982                                  "field %s of %t: %q", f, ct, 
1983                                  sRef_unparse (s)),
1984                         g_currentloc);
1985           
1986           cstring_free (f);
1987           return sRef_undefined;
1988         }
1989       else 
1990         {
1991           if (ctype_isAbstract (ct) && context_inHeader ())
1992             {
1993               voptgenerror 
1994                 (FLG_ABSTRACT,
1995                  message
1996                  ("Modifies clause in header file accesses abstract "
1997                   "type %s (interface modifies clause should not depend "
1998                   "on or expose type representation): %q",
1999                   ctype_unparse (ct),
2000                   sRef_unparse (s)),
2001                  g_currentloc);
2002             }
2003         }
2004       
2005       cstring_markOwned (f);
2006       return (sRef_makeField (s, f));
2007     }
2008   else
2009     {
2010       voptgenerror 
2011         (FLG_TYPE,
2012          message ("Modifies clause dereferences non-pointer (type %s): %q",
2013                   ctype_unparse (rt),
2014                   sRef_unparse (s)),
2015          g_currentloc);
2016       
2017       cstring_free (f);
2018       return s;
2019     }
2020 }
2021
2022 /*@dependent@*/ sRef clabstract_unrecognizedGlobal (cstring s)
2023 {
2024   if (cstring_equalLit (s, "nothing"))
2025     {
2026       return sRef_makeNothing ();
2027     }
2028   else if (cstring_equalLit (s, "internalState"))
2029     {
2030       return sRef_makeInternalState ();
2031     }
2032   else if (cstring_equalLit (s, "fileSystem")
2033            || cstring_equalLit (s, "systemState"))
2034     {
2035       return sRef_makeSystemState ();
2036     }
2037   else
2038     {
2039       voptgenerror 
2040         (FLG_UNRECOG, 
2041          message ("Unrecognized identifier in globals list: %s", s), 
2042          g_currentloc);
2043       
2044       return sRef_undefined;
2045     }
2046 }
2047
2048 /*@exposed@*/ sRef modListArrowAccess (sRef s, cstring f)
2049 {
2050   ctype ct = sRef_getType (s);
2051   ctype rt = ctype_realType (ct);
2052
2053   if (ctype_isRealPointer (rt))
2054     {
2055       ctype b = ctype_baseArrayPtr (rt);
2056       ctype rb = ctype_realType (b);
2057
2058       if (ctype_isStructorUnion (rb))
2059         {
2060           uentry tf = uentryList_lookupField (ctype_getFields (rb), f);
2061       
2062           if (uentry_isUndefined (tf))
2063             {
2064               voptgenerror (FLG_TYPE,
2065                             message ("Modifies list arrow accesses non-existent "
2066                                      "field %s of %t: %q", f, b, 
2067                                      sRef_unparse (s)),
2068                             g_currentloc);
2069               
2070               cstring_free (f);
2071               return sRef_undefined;
2072             }
2073           else 
2074             {
2075               if (context_inHeader ())
2076                 {
2077                   if (ctype_isAbstract (b))
2078                     {
2079                       voptgenerror 
2080                         (FLG_ABSTRACT,
2081                          message
2082                          ("Modifies clause in header file arrow accesses abstract "
2083                           "type %s (interface modifies clause should not depend "
2084                           "on or expose type representation): %q",
2085                           ctype_unparse (b),
2086                           sRef_unparse (s)),
2087                          g_currentloc);
2088                     }
2089                 }
2090               else 
2091                 {
2092                   if (ctype_isAbstract (rt))
2093                     {
2094                       voptgenerror 
2095                         (FLG_ABSTRACT,
2096                          message
2097                          ("Modifies clause arrow accesses inaccessible abstract "
2098                           "type %s (interface modifies clause should not depend "
2099                           "on or expose type representation): %q",
2100                           ctype_unparse (rt),
2101                           sRef_unparse (s)),
2102                          g_currentloc);
2103                     }
2104                 }
2105             }
2106
2107           cstring_markOwned (f);
2108           return (sRef_makeArrow (s, f));
2109         }
2110       else
2111         {
2112           voptgenerror 
2113             (FLG_TYPE,
2114              message ("Modifies clause arrow accesses pointer to "
2115                       "non-structure (type %s): %q",
2116                       ctype_unparse (rt),
2117                       sRef_unparse (s)),
2118              g_currentloc);
2119         }
2120     }
2121   else
2122     {
2123       voptgenerror 
2124         (FLG_TYPE,
2125          message ("Modifies clause arrow accesses non-pointer (type %s): %q",
2126                   ctype_unparse (rt),
2127                   sRef_unparse (s)),
2128          g_currentloc);
2129     }
2130
2131   cstring_free (f);
2132   return s;
2133 }
2134
2135 sRef checkStateClausesId (uentry ue)
2136 {
2137   cstring s = uentry_rawName (ue);
2138
2139   if (sRef_isFileOrGlobalScope (uentry_getSref (ue)))
2140     {
2141       voptgenerror 
2142         (FLG_COMMENTERROR,
2143          message ("Global variable %s used state clause.  (Global variables "
2144                   "are not recognized in state clauses.  If there is "
2145                   "sufficient interest in support for this, it may be "
2146                   "added to a future release.  Send mail to "
2147                   "info@splint.org.)",
2148                   s),
2149          g_currentloc);
2150       
2151       return sRef_undefined;
2152     }
2153   else
2154     {
2155       if (cstring_equalLit (s, "result"))
2156         {
2157           if (optgenerror 
2158               (FLG_SYNTAX, 
2159                message ("Special clause list uses %s which is a variable and has special "
2160                         "meaning in a modifies list.  (Special meaning assumed.)", s), 
2161                g_currentloc))
2162             {
2163               uentry_showWhereDeclared (ue);
2164             }
2165         }
2166
2167       return uentry_getSref (ue);
2168     }
2169 }
2170 /*drl:1/19/2001
2171   oops to 1/8/2000
2172   date is wronge ..
2173   don;t know what the real date is...
2174   
2175 */
2176
2177 /*drl
2178   added 1/8/2000
2179   based on checkSpecClausesId
2180   called by grammar
2181 */
2182
2183 sRef checkbufferConstraintClausesId (uentry ue)
2184 {
2185   sRef sr;
2186   cstring s = uentry_rawName (ue);
2187
2188   if (cstring_equalLit (s, "result"))
2189     {
2190       if (optgenerror 
2191           (FLG_SYNTAX, 
2192            message ("Function clause list uses %s which is a variable and has special "
2193                     "meaning in a modifies list.  (Special meaning assumed.)", s), 
2194            g_currentloc))
2195         {
2196           uentry_showWhereDeclared (ue);
2197         }
2198     }
2199   
2200   DPRINTF (("constraint id: %s", uentry_unparseFull (ue)));
2201   sr = uentry_getSref (ue);
2202
2203   if (sRef_isInvalid (sr) )
2204     {
2205       llfatalerrorLoc (cstring_makeLiteral("Macro defined constants can not be used in function constraints unless they are specifed with the constant annotation.  To use a macro defined constant include an annotation of the form /*@constant <type> <name>=<value>@*/ somewhere before the function constraint.  This restriction may be removed in future releases if it is determined to be excessively burdensome." ));
2206     }
2207   return sRef_saveCopy (sr); /*@i523 why the saveCopy? */
2208 }
2209
2210 void checkModifiesId (uentry ue)
2211 {
2212   cstring s = uentry_rawName (ue);
2213
2214   if (cstring_equalLit (s, "nothing")
2215       || cstring_equalLit (s, "internalState")
2216       || cstring_equalLit (s, "systemState")
2217       || (cstring_equalLit (s, "fileSystem")))
2218     {
2219       if (optgenerror 
2220           (FLG_SYNTAX, 
2221            message ("Modifies list uses %s which is a variable and has special "
2222                     "meaning in a modifies list.  (Special meaning assumed.)", s), 
2223            g_currentloc))
2224         {
2225           uentry_showWhereDeclared (ue);
2226         }
2227     }
2228 }
2229
2230 /*@exposed@*/ sRef fixModifiesId (cstring s) 
2231 {
2232   sRef ret;
2233   cstring pname = makeParam (s);
2234   uentry ue = usymtab_lookupSafe (pname);
2235
2236   cstring_free (pname);
2237
2238   if (cstring_equalLit (s, "nothing"))
2239     {
2240       ret = sRef_makeNothing ();
2241     }
2242   else if (cstring_equalLit (s, "internalState"))
2243     {
2244       ret = sRef_makeInternalState ();
2245     }
2246   else if (cstring_equalLit (s, "fileSystem")
2247            || cstring_equalLit (s, "systemState"))
2248     {
2249       ret = sRef_makeSystemState ();
2250     }
2251   else
2252     {
2253       ret = sRef_undefined;
2254     }
2255
2256   if (sRef_isValid (ret))
2257     {
2258       if (uentry_isValid (ue))
2259         {
2260           voptgenerror 
2261             (FLG_SYNTAX, 
2262              message ("Modifies list uses %s which is a parameter and has special "
2263                       "meaning in a modifies list.  (Special meaning assumed.)", s), 
2264              g_currentloc);
2265         }
2266     }
2267   else
2268     {
2269       if (uentry_isValid (ue))
2270         {
2271           ret = uentry_getSref (ue);
2272         }
2273       else
2274         {
2275           fileloc loc = fileloc_decColumn (g_currentloc, size_toInt (cstring_length (s)));
2276           ret = sRef_undefined;
2277
2278           voptgenerror 
2279             (FLG_UNRECOG, 
2280              message ("Unrecognized identifier in modifies comment: %s", s), 
2281              loc);
2282
2283           fileloc_free (loc);
2284         }
2285     }
2286   
2287   return ret;
2288 }
2289
2290 sRef fixStateClausesId (cstring s) 
2291 {
2292   sRef ret;
2293   cstring pname = makeParam (s);
2294   uentry ue = usymtab_lookupSafe (pname);
2295
2296   cstring_free (pname);
2297
2298   if (cstring_equalLit (s, "result"))
2299     {
2300       ret = sRef_makeResult (ctype_unknown);
2301     }
2302   else
2303     {
2304       ret = sRef_undefined;
2305     }
2306
2307   if (sRef_isValid (ret))
2308     {
2309       if (uentry_isValid (ue))
2310         {
2311           voptgenerror 
2312             (FLG_SYNTAX, 
2313              message ("Function clause uses %s which is a parameter and has special "
2314                       "meaning in a function clause.  (Special meaning assumed.)", s), 
2315              g_currentloc);
2316         }
2317     }
2318   else
2319     {
2320       if (uentry_isValid (ue))
2321         {
2322           ret = uentry_getSref (ue);
2323
2324           if (sRef_isFileOrGlobalScope (ret))
2325             {
2326               voptgenerror 
2327                 (FLG_SYNTAX, 
2328                  message ("Global variable %s used in function clause.  (Global variables "
2329                           "are not recognized in function clauses.  If there is "
2330                           "sufficient interest in support for this, it may be "
2331                           "added to a future release.  Send mail to "
2332                           "info@splint.org.)",
2333                           s), 
2334                  g_currentloc);
2335               
2336               ret = sRef_undefined;
2337             }
2338         }
2339       else
2340         {
2341           /*@i222@*/
2342           /*drl handle structure invariant */
2343
2344           /*@i222@*/
2345           /*check that we're in a structure */
2346 # if 0\r
2347                   /*@unused@*/    uentryList ueL;
2348           /*@unused@*/ uentry ue2;
2349           /*@unused@*/ ctype ct;\r
2350 # endif
2351           fileloc loc = fileloc_decColumn (g_currentloc, size_toInt (cstring_length (s)));
2352           ret = sRef_undefined; 
2353 # if 0
2354           /*drl commenting this out for now 
2355           ct = context_getLastStruct ( ct );
2356
2357           llassert( ctype_isStruct(ct) );
2358
2359           ueL =  ctype_getFields (ct);
2360
2361           ue2 = uentryList_lookupField (ueL, s);
2362
2363           if (!uentry_isUndefined(ue2) )
2364             {
2365               ret = uentry_getSref(ue2);
2366               
2367               DPRINTF((
2368                        message("Got field in structure in the annotation constraint: %s (or sref: %s)", s, sRef_unparse(ret) )
2369                        ));
2370               
2371               return ret;
2372             }
2373           */\r
2374 # endif\r
2375
2376           voptgenerror 
2377             (FLG_UNRECOG, 
2378              message ("Unrecognized identifier in function clause: %s", s), 
2379              loc);
2380
2381           fileloc_free (loc);
2382         }
2383     }
2384   
2385   return ret;
2386 }
2387
2388 sRef modListArrayFetch (/*@exposed@*/ sRef s, /*@unused@*/ sRef mexp)
2389 {
2390   ctype ct = sRef_getType (s);
2391   ctype rt = ctype_realType (ct);
2392
2393   if (ctype_isAP (rt))
2394     {
2395       if (context_inHeader () && ctype_isAbstract (ct))
2396         {
2397           voptgenerror 
2398             (FLG_ABSTRACT,
2399              message
2400              ("Modifies clause in header file indexes abstract "
2401               "type %s (interface modifies clause should not depend "
2402               "on or expose type representation): %q",
2403               ctype_unparse (ct),
2404               sRef_unparse (s)),
2405              g_currentloc);
2406         }
2407       
2408       return (sRef_makeAnyArrayFetch (s));
2409     }
2410   else
2411     {
2412       voptgenerror
2413         (FLG_TYPE,
2414          message
2415          ("Implementation modifies clause uses array fetch on non-array (type %s): %q",
2416           ctype_unparse (ct), sRef_unparse (s)),
2417          g_currentloc);
2418       return s;
2419     }
2420 }
2421
2422 static void clabstract_prepareFunction (uentry e)
2423 {
2424   uentry_checkParams (e);
2425   DPRINTF (("After prepare: %s", uentry_unparseFull (e)));
2426 }
2427
2428 sRef clabstract_checkGlobal (exprNode e)
2429 {
2430   sRef s;
2431   llassert (exprNode_isInitializer (e));
2432
2433   s = exprNode_getSref (e);
2434   DPRINTF (("Initializer: %s -> %s", exprNode_unparse (e), sRef_unparse (s)));
2435
2436   exprNode_free (e);
2437   return sRef_copy (s);
2438 }
This page took 0.226135 seconds and 5 git commands to generate.