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