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