]> andersk Git - splint.git/blob - src/clabstract.c
ab21e50f57454bfe79fcb5de64182c590e5ed6ea
[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   DPRINTF (("Enter function: %s", uentry_unparseFull (ue)));
635   context_enterFunction (ue);
636   enterFunctionParams (uentry_getParams (ue));
637
638   resetStorageClass ();
639   DPRINTF (("Function: %s", uentry_unparseFull (ue)));
640   return (ue);
641 }
642
643 /*
644 ** for now, no type checking
645 ** (must check later though!)
646 */
647
648 static /*@only@*/ uentry globalDeclareOldStyleFunction (idDecl tid)
649 {
650   uentry ue;
651
652   /*
653   ** check has been moved here...
654   */
655
656   if (cstring_equalLit (idDecl_observeId (tid), "main"))
657     {
658       context_setFlagTemp (FLG_MAINTYPE, FALSE);
659     }
660
661   ue = uentry_makeIdFunction (tid);
662   reflectStorageClass (ue);
663   reflectSpecialCode (ue);
664   reflectArgsUsed (ue);
665   uentry_setDefined (ue, g_currentloc);
666   uentry_checkParams (ue);
667   resetStorageClass ();
668
669   /* context_enterOldStyleScope (); */
670
671   return (ue);
672 }
673
674 static void oldStyleDeclareFunction (/*@only@*/ uentry e)
675 {
676   uentryList params = saveParamList;
677   ctype rt = uentry_getType (e);
678
679   llassert (ctype_isFunction (rt));
680
681   if (uentry_hasStateClauseList (e) 
682       || uentry_hasConditions (e))
683     {
684       llfatalerror (message ("%q: Old-style function declaration uses a clause (rewrite with function parameters): %q",
685                              fileloc_unparse (g_currentloc), uentry_unparse (e)));
686     }
687
688   e = usymtab_supGlobalEntryReturn (e);
689
690   context_enterFunction (e);
691   enterFunctionParams (params);
692   saveParamList = uentryList_undefined;
693   resetStorageClass ();
694 }
695
696 static void oldStyleCompleteFunction (/*@only@*/ uentry e)
697 {
698   uentryList params = saveParamList;
699   ctype rt = uentry_getType (e);
700
701   llassert (ctype_isFunction (rt));
702
703   if (uentry_hasStateClauseList (e) 
704       || uentry_hasConditions (e))
705     {
706       llfatalerror (message ("%q: Old-style function declaration uses a clause (rewrite with function parameters): %q",
707                              fileloc_unparse (g_currentloc), uentry_unparse (e)));
708     }
709
710   e = usymtab_supGlobalEntryReturn (e);
711
712   context_completeOldStyleFunction (e);
713   enterFunctionParams (params);
714   saveParamList = uentryList_undefined;
715   resetStorageClass ();
716 }
717
718 void clabstract_declareFunction (idDecl tid) /*@globals undef saveFunction; @*/
719 {
720   uentry ue;
721
722   DPRINTF (("Declare function: %s", idDecl_unparse (tid)));
723   
724   if (ProcessingParams)
725     {
726       ue = globalDeclareOldStyleFunction (tid);
727       saveFunction = ue;
728       DPRINTF (("Set save function: %s", uentry_unparseFull (ue)));
729     }
730   else
731     {
732       saveFunction = uentry_undefined;
733
734       if (context_inRealFunction ())
735         {
736           ue = uentry_makeVariableLoc (idDecl_observeId (tid), ctype_unknown);
737
738           llparseerror (message ("Function declared inside function: %q",
739                                  idDecl_unparse (tid)));
740           
741           context_quietExitFunction ();
742           ue = usymtab_supEntryReturn (ue);
743         }
744       else
745         {
746           if (context_inInnerScope ())
747             {
748               llparseerror (message ("Declaration in inner context: %q",
749                                      idDecl_unparse (tid)));
750               
751               sRef_setGlobalScope ();
752               ue = uentry_makeVariableLoc (idDecl_observeId (tid), 
753                                            ctype_unknown);
754               ue = usymtab_supGlobalEntryReturn (ue);
755               sRef_clearGlobalScope ();
756             }
757           else
758             {
759               ue = clabstract_globalDeclareFunction (tid);
760             }
761         }
762       
763       resetGlobals ();
764     }
765
766   resetStorageClass ();
767   idDecl_free (tid);
768 }
769
770 void declareStaticFunction (idDecl tid) /*@globals undef saveFunction; @*/
771 {
772   uentry ue;
773
774   DPRINTF (("Declare static funciton: %s", idDecl_unparse (tid)));
775
776   if (ProcessingParams)
777     {
778       ue = globalDeclareOldStyleFunction (tid);
779       saveFunction = ue;
780     }
781   else
782     {
783       saveFunction = uentry_undefined;
784
785       if (context_inRealFunction ())
786         {
787           ue = uentry_makeVariableLoc (idDecl_observeId (tid), ctype_unknown);
788
789           llparseerror (message ("Function declared inside function: %q",
790                                  idDecl_unparse (tid)));
791           
792           context_quietExitFunction ();
793           ue = usymtab_supEntryReturn (ue);
794         }
795       else
796         {
797           if (context_inInnerScope ())
798             {
799               llparseerror (message ("Declaration in inner context: %q",
800                                      idDecl_unparse (tid)));
801               
802               sRef_setGlobalScope ();
803               ue = uentry_makeVariableLoc (idDecl_observeId (tid), 
804                                            ctype_unknown);
805               ue = usymtab_supGlobalEntryReturn (ue);
806               sRef_clearGlobalScope ();
807             }
808           else
809             {
810               ctype deftype = idDecl_getCtype (tid);
811               ctype rettype;
812               
813               if (ctype_isFunction (deftype))
814                 {
815                   rettype = ctype_getReturnType (deftype);
816                 }
817               else
818                 {
819                   rettype = ctype_unknown;
820                 }
821               
822               /*
823               ** check has been moved here...
824               */
825               
826               if (ctype_isFunction (idDecl_getCtype (tid)))
827                 {
828                   ue = uentry_makeIdFunction (tid);
829                   reflectSpecialCode (ue);
830                   reflectArgsUsed (ue);
831                 }
832               else
833                 {    
834                   llparseerror (message ("Inconsistent function declaration: %q",
835                                          idDecl_unparse (tid)));
836                   
837                   tid = idDecl_replaceCtype 
838                     (tid, ctype_makeFunction (ctype_unknown, uentryList_undefined));
839                   ue = uentry_makeIdFunction (tid);
840                 }
841               
842               reflectStorageClass (ue);
843               uentry_setStatic (ue);
844
845               uentry_checkParams (ue);
846         
847               DPRINTF (("Sub global entry: %s", uentry_unparse (ue)));
848               ue = usymtab_supGlobalEntryReturn (ue);
849
850               context_enterFunction (ue);
851               enterFunctionParams (uentry_getParams (ue));
852               resetStorageClass ();
853             }
854         }
855       
856       resetGlobals ();
857     }
858   
859   resetStorageClass ();
860   idDecl_free (tid);
861 }
862
863 void
864 checkTypeDecl (uentry e, ctype rep)
865 {
866   cstring n = uentry_getName (e);
867
868   DPRINTF (("Check type decl: %s", uentry_unparseFull (e)));
869
870   if (cstring_equal (context_getBoolName (), n))
871     {
872       ctype rrep = ctype_realType (rep);
873       
874       /*
875       ** for abstract enum types, we need to fix the enum members:
876       ** they should have the abstract type, not the rep type.
877       */
878       
879       if (ctype_isEnum (ctype_realType (rrep)))
880         {
881           enumNameList el = ctype_elist (rrep);
882           
883           enumNameList_elements (el, ye)
884             {
885               if (usymtab_existsGlob (ye))
886                 {
887                   uentry ue = usymtab_lookupSafe (ye);
888                   uentry_setType (ue, ctype_bool);
889                 }
890
891               if (cstring_equal (context_getTrueName (), ye)
892                   || cstring_equal (context_getFalseName (), ye))
893                 {
894                   ;
895                 }
896               else
897                 {
898                   vgenhinterror 
899                     (FLG_SYNTAX,
900                      message ("Member of boolean enumerated type definition "
901                               "does not match name set to represent TRUE "
902                               "or FALSE: %s",
903                               ye),
904                      message ("Use -boolfalse and -booltrue to set the "
905                               "name of false and true boolean values."),
906                      uentry_whereDefined (e));
907                 }
908             } end_enumNameList_elements;
909         }
910     }
911
912   if (usymtab_exists (n))
913     {
914       usymId llm = usymtab_getId (n);
915       uentry le  = usymtab_getTypeEntry (llm);
916
917       uentry_setDeclared (e, g_currentloc); 
918       uentry_setSref (e, sRef_makeGlobal (llm, uentry_getType (le), stateInfo_currentLoc ()));
919
920       DPRINTF (("Here we are: %s / %s",
921                 n, context_getBoolName ()));
922       
923       if (uentry_isAbstractDatatype (le))
924         {
925           ctype rrep = ctype_realType (rep);
926
927           DPRINTF (("Abstract type: %s", uentry_unparseFull (le)));
928
929           /*
930           ** for abstract enum types, we need to fix the enum members:
931           ** they should have the abstract type, not the rep type.
932           */
933
934           if (ctype_isEnum (ctype_realType (rrep)))
935             {
936               ctype at = uentry_getAbstractType (le);
937               enumNameList el = ctype_elist (rrep);
938
939               enumNameList_elements (el, ye)
940                 {
941                   if (usymtab_existsGlob (ye))
942                     {
943                       uentry ue = usymtab_lookupSafe (ye);
944
945                       llassert (uentry_isEitherConstant (ue));
946                       llassertprint (ctype_match (uentry_getType (ue), rrep),
947                                      ("Bad enum: %s / %s",
948                                       uentry_unparse (ue),
949                                       ctype_unparse (rrep)));
950                       
951                       uentry_setType (ue, at);
952                     }
953                 } end_enumNameList_elements;
954             }
955           
956           if (uentry_isMutableDatatype (le))
957             {
958               /* maybe more complicated if abstract and immutable ? */
959
960               if (!ctype_isRealPointer (rep) && !ctype_isRealAbstract (rep))
961                 {
962                   voptgenerror 
963                     (FLG_MUTREP,
964                      message ("Mutable abstract type %s declared without pointer "
965                               "indirection: %s (violates assignment semantics)",
966                               n, ctype_unparse (rep)),
967                      uentry_whereDefined (e));
968                   
969                   uentry_setMutable (e);
970                 }
971             }
972         }
973     }
974   else
975     {
976       fileloc fl = uentry_whereDeclared (e);
977
978       if (context_getFlag (FLG_LIKELYBOOL)
979           && !context_getFlag (FLG_BOOLINT))
980         {
981           if ((cstring_equalLit (n, "BOOL")
982                || cstring_equalLit (n, "Bool")
983                || cstring_equalLit (n, "bool")
984                || cstring_equalLit (n, "boolean")
985                || cstring_equalLit (n, "Boolean")
986                || cstring_equalLit (n, "BOOLEAN"))
987               && !(cstring_equal (n, context_getBoolName ())))
988             {
989               if (context_setBoolName ()) {
990                 voptgenerror 
991                   (FLG_LIKELYBOOL,
992                    message ("Type %s is probably meant as a boolean type, but does "
993                             "not match the boolean type name \"%s\".",
994                             n,
995                             context_getBoolName ()),
996                    fl);
997               } else
998                 voptgenerror 
999                   (FLG_LIKELYBOOL,
1000                    message ("Type %s is probably meant as a boolean type, "
1001                             "but the boolean type name is not set. "
1002                             "Use -booltype %s to set it.",
1003                             n,
1004                             n),
1005                    fl);
1006                 }
1007         }
1008
1009       if (!uentry_isStatic (e)
1010           && !ctype_isFunction (uentry_getType (e)) 
1011           && !fileloc_isLib (fl) 
1012           && !fileloc_isImport (fl)
1013           && fileloc_isHeader (fl))
1014         {
1015           voptgenerror (FLG_EXPORTTYPE,
1016                         message ("Type exported, but not specified: %s\n", n),
1017                         fl);
1018         }
1019     }
1020
1021   cstring_free (n);
1022 }
1023
1024 uentryList
1025 fixUentryList (idDeclList tl, qtype q)
1026 {
1027   uentryList f = uentryList_new ();
1028   
1029   idDeclList_elements (tl, i)
1030   {
1031     if (idDecl_isDefined (i))
1032       {
1033         uentry ue;
1034         uentry old;
1035         ctype rt;
1036
1037         (void) idDecl_fixBase (i, q);
1038
1039         /*
1040         ** implicit annotations 
1041         */
1042
1043         (void) fixStructDecl (i);
1044
1045         ue = uentry_makeIdVariable (i);
1046         rt = ctype_realType (uentry_getType (ue));
1047
1048         /*
1049         ** where is this here???
1050
1051         if (ctype_isArray (rt) || ctype_isSU (rt))
1052           {
1053             sRef_setAllocated (uentry_getSref (ue), uentry_whereDefined (ue));
1054           }
1055
1056         **
1057         */
1058
1059         if (uentry_isValid (old = uentryList_lookupField (f, uentry_rawName (ue))))
1060           {
1061             if (optgenerror (FLG_SYNTAX,
1062                              message ("Field name reused: %s", uentry_rawName (ue)),
1063                              uentry_whereDefined (ue)))
1064               {
1065                 llgenmsg (message ("Previous use of %s", uentry_rawName (ue)),
1066                           uentry_whereDefined (old));
1067               }
1068           }
1069         
1070         f = uentryList_add (f, ue);
1071       }
1072   } end_idDeclList_elements;
1073
1074   idDeclList_free (tl);
1075   return (f);
1076 }
1077
1078 /*
1079 ** This is a hack to support unnamed struct/union fields as done by
1080 ** Microsoft VC++.  It is not supported by the ANSI standard.  
1081 **
1082 ** The inner fields are added to the outer structure.  This is meaningful
1083 ** for nesting structs inside unions, but lclint does no related 
1084 ** checking.
1085 */
1086
1087 uentryList
1088 fixUnnamedDecl (qtype q)
1089 {
1090   ctype ct = ctype_realType (qtype_getType (q));
1091
1092   if (ctype_isStruct (ct) || ctype_isUnion (ct))
1093     {
1094       uentryList res = ctype_getFields (ct);
1095
1096       return (uentryList_copy (res));
1097     }
1098   else
1099     {      
1100       BADBRANCHCONT;
1101     }
1102
1103   return uentryList_undefined;
1104 }
1105
1106 void setStorageClass (storageClassCode sc)
1107 {
1108   storageClass = sc;
1109 }
1110
1111 void
1112 setProcessingIterVars (uentry iter)
1113 {
1114   ProcessingIterVars = TRUE;
1115   currentIter = iter;
1116   saveIterParamNo = 0;
1117 }
1118
1119 void
1120 setProcessingGlobalsList ()
1121 {
1122   ProcessingGlobals = TRUE;
1123   fcnNoGlobals = FALSE;
1124 }
1125
1126 static bool ProcessingGlobMods = FALSE;
1127
1128 void
1129 setProcessingGlobMods ()
1130 {
1131   ProcessingGlobMods = TRUE;
1132 }
1133
1134 void
1135 clearProcessingGlobMods ()
1136 {
1137   ProcessingGlobMods = FALSE;
1138 }
1139
1140 bool
1141 isProcessingGlobMods ()
1142 {
1143   return (ProcessingGlobMods);
1144 }
1145
1146 static void resetGlobals (void)
1147 {
1148   ProcessingGlobals = FALSE;
1149   fcnNoGlobals = FALSE;
1150 }
1151
1152 void
1153 unsetProcessingGlobals ()
1154 {
1155   ProcessingGlobals = FALSE;
1156 }
1157
1158 void
1159 setProcessingVars (/*@only@*/ qtype q)
1160 {
1161   ProcessingVars = TRUE;
1162   qtype_free (processingType);
1163   processingType = q;
1164 }
1165
1166 static void
1167 setGenericParamList (/*@dependent@*/ uentryList pm)
1168 {
1169   ProcessingParams = TRUE;
1170   saveParamList = pm;
1171 }
1172
1173 void
1174 setProcessingTypedef (qtype q)
1175 {
1176   ProcessingTypedef = TRUE;
1177
1178   qtype_free (processingType);
1179   processingType = q;
1180 }
1181
1182 void
1183 unsetProcessingVars ()
1184 {
1185   resetStorageClass ();
1186   ProcessingVars = FALSE;
1187 }
1188
1189 void 
1190 oldStyleDoneParams ()
1191 {  
1192   if (ProcessingParams)
1193     {
1194       if (uentry_isInvalid (saveFunction))
1195         {
1196           llbuglit ("unsetProcessingVars: no saved function\n");
1197         }
1198       else
1199         {
1200           ctype ct = ctype_getReturnType (uentry_getType (saveFunction));
1201           uentryList params = uentryList_copy (saveParamList);
1202           ctype ct2 = ctype_makeFunction (ct, params);
1203
1204           uentry_setType (saveFunction, ct2);
1205           ProcessingParams = FALSE;
1206
1207           oldStyleCompleteFunction (saveFunction);
1208           saveFunction = uentry_undefined;
1209           resetGlobals ();
1210         }
1211     }
1212   else
1213     {
1214       /*
1215       ** If the paramlist used a type name, we could be here.
1216       */
1217
1218       llfatalerror (message ("%q: Old-style function parameter list uses a "
1219                              "type name.", fileloc_unparse (g_currentloc)));
1220     }
1221 }
1222
1223 void 
1224 checkDoneParams ()
1225 {
1226   if (uentry_isValid (saveFunction))
1227     {
1228       /*
1229       ** old style declaration
1230       */
1231
1232       ctype ct = ctype_getReturnType (uentry_getType (saveFunction));
1233       ctype ct2;
1234
1235       DPRINTF (("save function: %s", uentry_unparseFull (saveFunction)));
1236
1237       uentryList_elements (saveParamList, current)
1238         {
1239           uentry_setType (current, ctype_int); /* all params are ints */
1240         } end_uentryList_elements; 
1241
1242       ct2 = ctype_makeParamsFunction (ct, uentryList_copy (saveParamList));
1243       
1244       uentry_setType (saveFunction, ct2);
1245       ProcessingParams = FALSE;
1246       
1247       oldStyleDeclareFunction (saveFunction);
1248       saveFunction = uentry_undefined;
1249     }
1250 }
1251
1252 void clabstract_declareType (/*@only@*/ exprNodeList decls, /*@only@*/ warnClause warn)
1253 {
1254   llassert (ProcessingTypedef);
1255
1256   if (warnClause_isDefined (warn))
1257     {
1258       exprNodeList_elements (decls, el)
1259         {
1260           uentry ue = exprNode_getUentry (el);
1261           cstring uname = uentry_getName (ue);
1262
1263           DPRINTF (("Entry: %s", exprNode_unparse (el)));
1264
1265           /*
1266           ** Need to lookup again to make sure we have the right one...
1267           */
1268
1269           ue = usymtab_lookupGlob (uname);
1270
1271           llassert (uentry_isValid (ue));
1272           llassert (uentry_isDatatype (ue));
1273
1274           DPRINTF (("Warning for %s: %s",
1275                     uentry_unparse (ue), warnClause_unparse (warn)));
1276
1277           uentry_addWarning (ue, warnClause_copy (warn));
1278         } end_exprNodeList_elements;
1279     }
1280
1281   warnClause_free (warn);
1282   exprNodeList_free (decls);
1283   unsetProcessingTypedef ();
1284 }
1285
1286 void
1287 unsetProcessingTypedef ()
1288 {
1289   ProcessingTypedef = FALSE;
1290 }
1291
1292 void checkConstant (qtype t, idDecl id) 
1293 {
1294   uentry e;
1295
1296   id = idDecl_fixBase (id, t);
1297   e = uentry_makeIdConstant (id);
1298
1299   reflectStorageClass (e);
1300   resetStorageClass ();
1301
1302   DPRINTF (("Constant: %s", uentry_unparseFull (e)));
1303   usymtab_supGlobalEntry (e);
1304 }
1305
1306 void checkValueConstant (qtype t, idDecl id, exprNode e) 
1307 {
1308   uentry ue;
1309
1310   id = idDecl_fixBase (id, t);
1311   ue = uentry_makeIdConstant (id);
1312   reflectStorageClass (ue);
1313   resetStorageClass ();
1314
1315   if (exprNode_isDefined (e))
1316     {
1317       if (!exprNode_matchType (uentry_getType (ue), e))
1318         {
1319           (void) gentypeerror 
1320             (exprNode_getType (e), e,
1321              uentry_getType (ue), exprNode_undefined,
1322              message ("Constant %q initialized to type %t, expects %t: %s",
1323                       uentry_getName (ue),  
1324                       exprNode_getType (e), 
1325                       uentry_getType (ue),
1326                       exprNode_unparse (e)),
1327              exprNode_loc (e));
1328         }
1329       else
1330         {
1331           if (exprNode_hasValue (e))
1332             {
1333               uentry_mergeConstantValue (ue, multiVal_copy (exprNode_getValue (e)));
1334             }
1335           else
1336             {
1337               DPRINTF (("No value: %s", exprNode_unparse (e)));
1338             }
1339         }
1340     }
1341
1342   DPRINTF (("Constant value: %s", uentry_unparseFull (ue)));
1343   usymtab_supGlobalEntry (ue);
1344 }
1345
1346 void processNamedDecl (idDecl t)
1347 {
1348   if (qtype_isUndefined (processingType))
1349     {
1350       llparseerror (message ("No type before declaration name: %q", idDecl_unparse (t)));
1351
1352       processingType = qtype_create (ctype_unknown);
1353     }
1354
1355   t = idDecl_fixBase (t, processingType);
1356
1357   DPRINTF (("Declare: %s", idDecl_unparse (t)));
1358   
1359   if (ProcessingGlobals)
1360     {
1361       cstring id = idDecl_getName (t);
1362       uentry ue = usymtab_lookupSafe (id);
1363       
1364       if (!uentry_isValid (ue))
1365         {
1366           llerror (FLG_UNRECOG,
1367                    message ("Variable used in globals list is undeclared: %s", id));
1368         }
1369       else
1370         {
1371           if (!ctype_match (uentry_getType (ue), idDecl_getCtype (t)))
1372             {
1373               voptgenerror 
1374                 (FLG_INCONDEFS,
1375                  message ("Variable %s used in globals list declared %s, "
1376                           "but listed as %s", 
1377                           id, ctype_unparse (uentry_getType (ue)), 
1378                           ctype_unparse (idDecl_getCtype (t))),
1379                  g_currentloc);
1380             }
1381           else
1382             {
1383               sRef sr = sRef_copy (uentry_getSref (ue));
1384               reflectGlobalQualifiers (sr, idDecl_getQuals (t));
1385             }
1386         }
1387     }
1388   else if (ProcessingVars)
1389     {
1390       uentry e;
1391       ctype ct;
1392       
1393       ct = ctype_realType (idDecl_getCtype (t));
1394
1395       if (ProcessingParams)
1396         {
1397           cstring id = idDecl_getName (t);
1398           int paramno = uentryList_lookupRealName (saveParamList, id);
1399
1400           if (paramno >= 0)
1401             {
1402               uentry cparam = uentryList_getN (saveParamList, paramno);
1403
1404               DPRINTF (("Processing param: %s", uentry_unparseFull (cparam)));
1405               uentry_setType (cparam, idDecl_getCtype (t));
1406               uentry_reflectQualifiers (cparam, idDecl_getQuals (t));
1407               uentry_setDeclaredOnly (cparam, context_getSaveLocation ());
1408               DPRINTF (("Processing param: %s", uentry_unparseFull (cparam)));
1409             }
1410           else
1411             {
1412               llfatalerrorLoc
1413                 (message ("Old style declaration uses unlisted parameter: %s", 
1414                           id));
1415             }
1416         }
1417       else
1418         {
1419           fileloc loc;
1420
1421           if (context_inIterDef ())
1422             {
1423               cstring pname = makeParam (idDecl_observeId (t));
1424               uentry p = usymtab_lookupSafe (pname);
1425
1426               cstring_free (pname);
1427
1428               if (uentry_isYield (p))
1429                   {
1430                       e = uentry_makeParam (t, sRef_getParam (uentry_getSref (p)));
1431                       uentry_checkYieldParam (p, e);
1432                       usymtab_supEntrySref (e);
1433                       return;
1434                   }
1435             }
1436           
1437           if ((hasSpecialCode () || argsUsed)
1438               && ctype_isFunction (idDecl_getCtype (t)))
1439               {
1440               e = uentry_makeIdFunction (t);
1441               reflectSpecialCode (e);
1442               reflectArgsUsed (e);
1443               }
1444           else
1445               {
1446                   e = uentry_makeIdVariable (t);
1447               }
1448           
1449           loc = uentry_whereDeclared (e);
1450           
1451           /*
1452             if (context_inGlobalScope ())
1453             {
1454             uentry_checkParams was here!
1455             }
1456           */
1457           
1458           if (ctype_isFunction (uentry_getType (e)))
1459             {
1460               clabstract_prepareFunction (e);
1461             }
1462           
1463           DPRINTF (("Superceding... %s", uentry_unparseFull (e)));
1464           e = usymtab_supEntrySrefReturn (e);
1465           DPRINTF (("After superceding... %s", uentry_unparseFull (e)));          
1466           
1467           if (uentry_isExtern (e) && !context_inGlobalScope ())
1468             {
1469               voptgenerror 
1470                 (FLG_NESTEDEXTERN,
1471                  message ("Declaration using extern inside function scope: %q",
1472                           uentry_unparse (e)),
1473                  g_currentloc);
1474               
1475               uentry_setDefined (e, fileloc_getExternal ());
1476               sRef_setDefined (uentry_getSref (e), fileloc_getExternal ());
1477             }
1478           
1479           if (uentry_isFunction (e))
1480             {
1481               if (!context_inXHFile ())
1482                 {
1483                   checkParamNames (e);
1484                 }
1485             }
1486           
1487           if (uentry_isVar (e) && uentry_isCheckedUnknown (e))
1488             {
1489               sRef sr = uentry_getSref (e);
1490               
1491               if (sRef_isLocalVar (sr))
1492                 {
1493                   if (context_getFlag (FLG_IMPCHECKMODINTERNALS))
1494                     {
1495                       uentry_setCheckMod (e);
1496                     }
1497                   else
1498                     {
1499                       uentry_setUnchecked (e);
1500                     }
1501                 }
1502               else if (sRef_isFileStatic (sr))
1503                 {
1504                   if (context_getFlag (FLG_IMPCHECKEDSTRICTSTATICS))
1505                     {
1506                       uentry_setCheckedStrict (e);
1507                     }
1508                   else if (context_getFlag (FLG_IMPCHECKEDSTATICS))
1509                     {
1510                       uentry_setChecked (e);
1511                     }
1512                   else if (context_getFlag (FLG_IMPCHECKMODSTATICS))
1513                     {
1514                       uentry_setCheckMod (e);
1515                     }
1516                   else
1517                     {
1518                       ;
1519                     }
1520                 }
1521               else /* real global */
1522                 {
1523                   llassert (sRef_isRealGlobal (sr));
1524                   
1525                   if (context_getFlag (FLG_IMPCHECKEDSTRICTGLOBALS))
1526                     {
1527                       uentry_setCheckedStrict (e);
1528                     }
1529                   else if (context_getFlag (FLG_IMPCHECKEDGLOBALS))
1530                     {
1531                       uentry_setChecked (e);
1532                     }
1533                   else if (context_getFlag (FLG_IMPCHECKMODGLOBALS))
1534                     {
1535                       uentry_setCheckMod (e);
1536                     }
1537                   else
1538                     {
1539                       ;
1540                     }
1541                 }
1542             }
1543         }
1544     }
1545   else if (ProcessingTypedef)
1546     {
1547       ctype ct = idDecl_getCtype (t);
1548       uentry e;
1549       
1550       DPRINTF (("Processing typedef: %s", ctype_unparse (ct)));
1551       
1552       e = uentry_makeIdDatatype (t);
1553
1554       if (cstring_equal (idDecl_getName (t), context_getBoolName ())) {
1555         ctype rt = ctype_realType (ct);
1556         
1557         if (ctype_isEnum (rt)) {
1558           ;
1559         } else {
1560           if (!(ctype_isInt (rt)
1561                 || ctype_isUnknown (rt)
1562                 || ctype_isChar (rt))) {
1563             (void) llgenerror
1564               (FLG_BOOLTYPE, 
1565                message ("Boolean type %s defined using non-standard type %s (integral, char or enum type expected)",
1566                         context_getBoolName (),
1567                         ctype_unparse (ct)),
1568                uentry_whereLast (e));
1569           }
1570           
1571           ct = ctype_bool;
1572           uentry_setType (e, ct);
1573         }
1574       }
1575
1576       reflectStorageClass (e);
1577       checkTypeDecl (e, ct);
1578       
1579       e = usymtab_supReturnTypeEntry (e);
1580     }
1581   else
1582     {
1583       llparseerror (message ("Suspect missing struct or union keyword: %q",
1584                              idDecl_unparse (t)));
1585     }
1586
1587   }
1588
1589 /*
1590 ** moved from grammar
1591 */
1592
1593 static idDecl fixStructDecl (/*@returned@*/ idDecl d)
1594 {
1595   if (ctype_isVisiblySharable (idDecl_getCtype (d)) 
1596       && context_getFlag (FLG_STRUCTIMPONLY))
1597     {
1598       if (!qualList_hasAliasQualifier (idDecl_getQuals (d)))
1599         {
1600           if (qualList_hasExposureQualifier (idDecl_getQuals (d)))
1601             {
1602               idDecl_addQual (d, qual_createDependent ());
1603             }
1604           else
1605             {
1606               idDecl_addQual (d, qual_createImpOnly ());
1607             }
1608         }
1609     }
1610
1611   return d;
1612 }
1613
1614 ctype
1615 declareUnnamedStruct (/*@only@*/ uentryList f)
1616 {
1617   DPRINTF (("Unnamed struct: %s", uentryList_unparse (f)));
1618
1619   if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
1620     {
1621       int num = uentryList_size (f);
1622       int max = context_getValue (FLG_NUMSTRUCTFIELDS);
1623
1624       if (num > max)
1625         {
1626           voptgenerror 
1627             (FLG_NUMSTRUCTFIELDS,
1628              message ("Structure declared with %d fields "
1629                       "(limit is set to %d)",
1630                       num, max),
1631              g_currentloc);
1632         }
1633     }
1634
1635   return (ctype_createUnnamedStruct (f));
1636 }
1637
1638 ctype
1639 declareUnnamedUnion (/*@only@*/ uentryList f)
1640 {
1641   if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
1642     {
1643       int num = uentryList_size (f);
1644       int max = context_getValue (FLG_NUMSTRUCTFIELDS);
1645
1646       if (num > max)
1647         {
1648           voptgenerror 
1649             (FLG_NUMSTRUCTFIELDS,
1650              message ("Union declared with %d fields "
1651                       "(limit is set to %d)",
1652                       num, max),
1653              g_currentloc);
1654         }
1655     }
1656
1657   return (ctype_createUnnamedUnion (f));
1658 }
1659
1660 ctype declareStruct (cstring id, /*@only@*/ uentryList f)
1661 {
1662   ctype ct; 
1663   uentry ue;
1664   int num = uentryList_size (f);
1665
1666   DPRINTF (("Declare struct: %s / %s", id, uentryList_unparse (f)));
1667
1668   ct = ctype_createStruct (cstring_copy (id), f);
1669
1670   DPRINTF (("Ctype: %s", ctype_unparse (ct)));
1671
1672   ue = uentry_makeStructTagLoc (id, ct);
1673
1674   DPRINTF (("ue: %s", uentry_unparseFull (ue)));
1675
1676   if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
1677     {
1678       int max = context_getValue (FLG_NUMSTRUCTFIELDS);
1679
1680       if (num > max)
1681         {
1682           voptgenerror 
1683             (FLG_NUMSTRUCTFIELDS,
1684              message ("Structure %q declared with %d fields "
1685                       "(limit is set to %d)",
1686                       uentry_getName (ue), num, max),
1687              uentry_whereLast (ue));
1688         }
1689     }
1690
1691   return (usymtab_supTypeEntry (ue));
1692 }
1693
1694 ctype declareUnion (cstring id, uentryList f)
1695 {
1696   ctype ct; 
1697   uentry ue;
1698   int num = uentryList_size (f);
1699
1700   ct = ctype_createUnion (cstring_copy (id), f);
1701   ue = uentry_makeUnionTagLoc (id, ct);
1702
1703   if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
1704     {
1705       int max = context_getValue (FLG_NUMSTRUCTFIELDS);
1706
1707       if (num > max)
1708         {
1709           voptgenerror 
1710             (FLG_NUMSTRUCTFIELDS,
1711              message ("Union %q declared with %d fields "
1712                       "(limit is set to %d)",
1713                       uentry_getName (ue), num, max),
1714              uentry_whereLast (ue));
1715         }
1716     }
1717
1718   return (usymtab_supTypeEntry (ue));
1719 }
1720
1721 ctype handleStruct (/*@only@*/ cstring id)
1722 {
1723   if (usymtab_existsStructTag (id))
1724     {
1725       ctype ct = uentry_getAbstractType (usymtab_lookupStructTag (id));
1726
1727       cstring_free (id);
1728       return ct;
1729     }
1730   else
1731     {
1732       return (ctype_createForwardStruct (id));
1733     }
1734 }
1735
1736 ctype handleUnion (/*@only@*/ cstring id)
1737 {
1738   if (usymtab_existsUnionTag (id))
1739     {
1740       ctype ret = uentry_getAbstractType (usymtab_lookupUnionTag (id));
1741       cstring_free (id);
1742       return (ret);
1743     }
1744   else
1745     {
1746       return (ctype_createForwardUnion (id));
1747     }
1748 }
1749
1750 ctype
1751 handleEnum (cstring id)
1752 {
1753   if (usymtab_existsEnumTag (id))
1754     {
1755       ctype ret = uentry_getAbstractType (usymtab_lookupEnumTag (id));
1756       cstring_free (id);
1757       return ret;
1758     }
1759   else
1760     {
1761       return (declareEnum (id, enumNameList_new ()));
1762     }
1763 }
1764
1765 bool processingIterVars (void) 
1766
1767   return ProcessingIterVars; 
1768 }
1769
1770 uentry getCurrentIter (void) 
1771 {
1772   return currentIter; 
1773 }
1774
1775 static bool flipOldStyle = FALSE;
1776 static bool flipNewStyle = TRUE;
1777
1778 void setFlipOldStyle ()          { flipOldStyle = TRUE; }
1779 bool isFlipOldStyle ()           { return flipOldStyle; }
1780 bool isNewStyle ()               { return flipNewStyle; }
1781 void setNewStyle ()              { flipNewStyle = TRUE; }
1782
1783 /*@dependent@*/ uentryList handleParamIdList (/*@dependent@*/ uentryList params)
1784 {  
1785   int paramno = 0;
1786
1787   /*
1788   ** this is a really YUCKY hack to handle old style
1789   ** declarations.
1790   */
1791   
1792   voptgenerror (FLG_OLDSTYLE,
1793                 cstring_makeLiteral ("Old style function declaration"),
1794                 g_currentloc); 
1795
1796   DPRINTF (("Handle old style params: %s", uentryList_unparseFull (params)));
1797
1798   uentryList_elements (params, current)
1799     {
1800       uentry_setParam (current);
1801       uentry_setSref (current, sRef_makeParam (paramno, ctype_unknown, stateInfo_makeLoc (uentry_whereLast (current))));
1802       paramno++;
1803     } end_uentryList_elements;
1804
1805   setGenericParamList (params);
1806   g_expectingTypeName = TRUE; 
1807
1808   return params;
1809 }
1810
1811 /*@dependent@*/ uentryList handleParamTypeList (/*@returned@*/ uentryList params)
1812 {
1813   if (flipOldStyle)
1814     {
1815       uentryList_fixMissingNames (params);
1816
1817       voptgenerror (FLG_OLDSTYLE, 
1818                     cstring_makeLiteral ("Old style function declaration."), 
1819                     g_currentloc); 
1820       
1821       setGenericParamList (params);
1822       flipOldStyle = FALSE;
1823       g_expectingTypeName = TRUE; 
1824     }
1825  
1826   return (params); 
1827 }
1828
1829 void
1830 doVaDcl ()
1831 {
1832   ctype c = ctype_unknown;
1833   cstring id = cstring_makeLiteral ("va_alist");
1834   uentry e;
1835
1836   if (ProcessingParams)
1837     {
1838       int i = uentryList_lookupRealName (saveParamList, id);
1839       
1840       if (i >= 0)
1841         {
1842           fileloc loc = context_getSaveLocation ();
1843           e = uentry_makeVariableSrefParam (id, c, loc, sRef_makeParam (i, c, stateInfo_makeLoc (loc)));
1844         }
1845       else
1846         {
1847           e = uentry_undefined; /* suppress gcc message */
1848           llfatalerrorLoc (cstring_makeLiteral ("va_dcl used without va_alist"));
1849         }
1850     }
1851   else
1852     {    
1853       llerror (FLG_SYNTAX, cstring_makeLiteral ("va_dcl used outside of function declaration"));
1854       e = uentry_makeVariableLoc (id, c);
1855     }
1856
1857   cstring_free (id);
1858   uentry_setUsed (e, g_currentloc);  
1859   usymtab_supEntrySref (e);
1860 }
1861
1862 /*@exposed@*/ sRef modListPointer (/*@exposed@*/ sRef s)
1863 {
1864   ctype ct = sRef_getType (s);
1865   ctype rt = ctype_realType (ct);
1866   
1867   if (ctype_isAP (rt))
1868     {
1869       if (context_inHeader () && ctype_isAbstract (ct))
1870         {
1871           voptgenerror 
1872             (FLG_ABSTRACT,
1873              message
1874              ("Modifies clause in header file dereferences abstract "
1875               "type %s (interface modifies clause should not depend "
1876               "on or expose type representation): %q",
1877               ctype_unparse (ct),
1878               sRef_unparse (s)),
1879              g_currentloc);
1880         }
1881
1882       return (sRef_constructPointer (s));
1883     }
1884   else
1885     {
1886       if (ctype_isKnown (rt))
1887         {
1888           voptgenerror 
1889             (FLG_TYPE,
1890              message ("Implementation modifies clause dereferences non-pointer (type %s): %q",
1891                       ctype_unparse (rt),
1892                       sRef_unparse (s)),
1893              g_currentloc);
1894         }
1895
1896       return s;
1897     }
1898 }
1899
1900 /*@exposed@*/ sRef modListFieldAccess (sRef s, cstring f)
1901 {
1902   ctype ct = sRef_getType (s);
1903   ctype rt = ctype_realType (ct);
1904   
1905   if (ctype_isStructorUnion (rt))
1906     {
1907       uentry tf = uentryList_lookupField (ctype_getFields (rt), f);
1908       
1909       if (uentry_isUndefined (tf))
1910         {
1911           voptgenerror (FLG_TYPE,
1912                         message ("Modifies list accesses non-existent "
1913                                  "field %s of %t: %q", f, ct, 
1914                                  sRef_unparse (s)),
1915                         g_currentloc);
1916           
1917           cstring_free (f);
1918           return sRef_undefined;
1919         }
1920       else 
1921         {
1922           if (ctype_isAbstract (ct) && context_inHeader ())
1923             {
1924               voptgenerror 
1925                 (FLG_ABSTRACT,
1926                  message
1927                  ("Modifies clause in header file accesses abstract "
1928                   "type %s (interface modifies clause should not depend "
1929                   "on or expose type representation): %q",
1930                   ctype_unparse (ct),
1931                   sRef_unparse (s)),
1932                  g_currentloc);
1933             }
1934         }
1935       
1936       cstring_markOwned (f);
1937       return (sRef_makeField (s, f));
1938     }
1939   else
1940     {
1941       voptgenerror 
1942         (FLG_TYPE,
1943          message ("Modifies clause dereferences non-pointer (type %s): %q",
1944                   ctype_unparse (rt),
1945                   sRef_unparse (s)),
1946          g_currentloc);
1947       
1948       cstring_free (f);
1949       return s;
1950     }
1951 }
1952
1953 /*@dependent@*/ sRef clabstract_unrecognizedGlobal (cstring s)
1954 {
1955   if (cstring_equalLit (s, "nothing"))
1956     {
1957       return sRef_makeNothing ();
1958     }
1959   else if (cstring_equalLit (s, "internalState"))
1960     {
1961       return sRef_makeInternalState ();
1962     }
1963   else if (cstring_equalLit (s, "fileSystem")
1964            || cstring_equalLit (s, "systemState"))
1965     {
1966       return sRef_makeSystemState ();
1967     }
1968   else
1969     {
1970       voptgenerror 
1971         (FLG_UNRECOG, 
1972          message ("Unrecognized identifier in globals list: %s", s), 
1973          g_currentloc);
1974       
1975       return sRef_undefined;
1976     }
1977 }
1978
1979 /*@exposed@*/ sRef modListArrowAccess (sRef s, cstring f)
1980 {
1981   ctype ct = sRef_getType (s);
1982   ctype rt = ctype_realType (ct);
1983
1984   if (ctype_isRealPointer (rt))
1985     {
1986       ctype b = ctype_baseArrayPtr (rt);
1987       ctype rb = ctype_realType (b);
1988
1989       if (ctype_isStructorUnion (rb))
1990         {
1991           uentry tf = uentryList_lookupField (ctype_getFields (rb), f);
1992       
1993           if (uentry_isUndefined (tf))
1994             {
1995               voptgenerror (FLG_TYPE,
1996                             message ("Modifies list arrow accesses non-existent "
1997                                      "field %s of %t: %q", f, b, 
1998                                      sRef_unparse (s)),
1999                             g_currentloc);
2000               
2001               cstring_free (f);
2002               return sRef_undefined;
2003             }
2004           else 
2005             {
2006               if (context_inHeader ())
2007                 {
2008                   if (ctype_isAbstract (b))
2009                     {
2010                       voptgenerror 
2011                         (FLG_ABSTRACT,
2012                          message
2013                          ("Modifies clause in header file arrow accesses abstract "
2014                           "type %s (interface modifies clause should not depend "
2015                           "on or expose type representation): %q",
2016                           ctype_unparse (b),
2017                           sRef_unparse (s)),
2018                          g_currentloc);
2019                     }
2020                 }
2021               else 
2022                 {
2023                   if (ctype_isAbstract (ct))
2024                     {
2025                       voptgenerror 
2026                         (FLG_ABSTRACT,
2027                          message
2028                          ("Modifies clause in header file arrow accesses abstract "
2029                           "type %s (interface modifies clause should not depend "
2030                           "on or expose type representation): %q",
2031                           ctype_unparse (ct),
2032                           sRef_unparse (s)),
2033                          g_currentloc);
2034                     }
2035                 }
2036             }
2037
2038           cstring_markOwned (f);
2039           return (sRef_makeArrow (s, f));
2040         }
2041       else
2042         {
2043           voptgenerror 
2044             (FLG_TYPE,
2045              message ("Modifies clause arrow accesses pointer to "
2046                       "non-structure (type %s): %q",
2047                       ctype_unparse (rt),
2048                       sRef_unparse (s)),
2049              g_currentloc);
2050         }
2051     }
2052   else
2053     {
2054       voptgenerror 
2055         (FLG_TYPE,
2056          message ("Modifies clause arrow accesses non-pointer (type %s): %q",
2057                   ctype_unparse (rt),
2058                   sRef_unparse (s)),
2059          g_currentloc);
2060     }
2061
2062   cstring_free (f);
2063   return s;
2064 }
2065
2066 sRef checkStateClausesId (uentry ue)
2067 {
2068   cstring s = uentry_rawName (ue);
2069
2070   if (sRef_isFileOrGlobalScope (uentry_getSref (ue)))
2071     {
2072       voptgenerror 
2073         (FLG_COMMENTERROR,
2074          message ("Global variable %s used special clause.  (Global variables "
2075                   "are not recognized in special clauses.  If there is "
2076                   "sufficient interest in support for this, it may be "
2077                   "added to a future release.  Send mail to "
2078                   "lclint@cs.virginia.edu.)",
2079                   s),
2080          g_currentloc);
2081       
2082       return sRef_undefined;
2083     }
2084   else
2085     {
2086       if (cstring_equalLit (s, "result"))
2087         {
2088           if (optgenerror 
2089               (FLG_SYNTAX, 
2090                message ("Special clause list uses %s which is a variable and has special "
2091                         "meaning in a modifies list.  (Special meaning assumed.)", s), 
2092                g_currentloc))
2093             {
2094               uentry_showWhereDeclared (ue);
2095             }
2096         }
2097
2098       return uentry_getSref (ue);
2099     }
2100 }
2101 /*drl:1/19/2001
2102   oops to 1/8/2000
2103   date is wronge ..
2104   don;t know what the real date is...
2105   
2106 */
2107
2108 /*drl
2109   added 1/8/2000
2110   based on checkSpecClausesId
2111   called by grammar
2112 */
2113
2114 sRef checkbufferConstraintClausesId (uentry ue)
2115 {
2116   cstring s = uentry_rawName (ue);
2117
2118   if (cstring_equalLit (s, "result"))
2119     {
2120       if (optgenerror 
2121           (FLG_SYNTAX, 
2122            message ("Function clause list uses %s which is a variable and has special "
2123                     "meaning in a modifies list.  (Special meaning assumed.)", s), 
2124            g_currentloc))
2125         {
2126           uentry_showWhereDeclared (ue);
2127         }
2128     }
2129   
2130   DPRINTF (("constrant id: %s", uentry_unparseFull (ue)));
2131   return sRef_saveCopy (uentry_getSref (ue)); /*@i523 why the saveCopy? */
2132 }
2133
2134 void checkModifiesId (uentry ue)
2135 {
2136   cstring s = uentry_rawName (ue);
2137
2138   if (cstring_equalLit (s, "nothing")
2139       || cstring_equalLit (s, "internalState")
2140       || cstring_equalLit (s, "systemState")
2141       || (cstring_equalLit (s, "fileSystem")))
2142     {
2143       if (optgenerror 
2144           (FLG_SYNTAX, 
2145            message ("Modifies list uses %s which is a variable and has special "
2146                     "meaning in a modifies list.  (Special meaning assumed.)", s), 
2147            g_currentloc))
2148         {
2149           uentry_showWhereDeclared (ue);
2150         }
2151     }
2152 }
2153
2154 /*@exposed@*/ sRef fixModifiesId (cstring s) 
2155 {
2156   sRef ret;
2157   cstring pname = makeParam (s);
2158   uentry ue = usymtab_lookupSafe (pname);
2159
2160   cstring_free (pname);
2161
2162   if (cstring_equalLit (s, "nothing"))
2163     {
2164       ret = sRef_makeNothing ();
2165     }
2166   else if (cstring_equalLit (s, "internalState"))
2167     {
2168       ret = sRef_makeInternalState ();
2169     }
2170   else if (cstring_equalLit (s, "fileSystem")
2171            || cstring_equalLit (s, "systemState"))
2172     {
2173       ret = sRef_makeSystemState ();
2174     }
2175   else
2176     {
2177       ret = sRef_undefined;
2178     }
2179
2180   if (sRef_isValid (ret))
2181     {
2182       if (uentry_isValid (ue))
2183         {
2184           voptgenerror 
2185             (FLG_SYNTAX, 
2186              message ("Modifies list uses %s which is a parameter and has special "
2187                       "meaning in a modifies list.  (Special meaning assumed.)", s), 
2188              g_currentloc);
2189         }
2190     }
2191   else
2192     {
2193       if (uentry_isValid (ue))
2194         {
2195           ret = uentry_getSref (ue);
2196         }
2197       else
2198         {
2199           fileloc loc = fileloc_decColumn (g_currentloc, cstring_length (s));
2200           ret = sRef_undefined;
2201
2202           voptgenerror 
2203             (FLG_UNRECOG, 
2204              message ("Unrecognized identifier in modifies comment: %s", s), 
2205              loc);
2206
2207           fileloc_free (loc);
2208         }
2209     }
2210   
2211   return ret;
2212 }
2213
2214 sRef fixStateClausesId (cstring s) 
2215 {
2216   sRef ret;
2217   cstring pname = makeParam (s);
2218   uentry ue = usymtab_lookupSafe (pname);
2219
2220   cstring_free (pname);
2221
2222   if (cstring_equalLit (s, "result"))
2223     {
2224       ret = sRef_makeResult (ctype_unknown);
2225     }
2226   else
2227     {
2228       ret = sRef_undefined;
2229     }
2230
2231   if (sRef_isValid (ret))
2232     {
2233       if (uentry_isValid (ue))
2234         {
2235           voptgenerror 
2236             (FLG_SYNTAX, 
2237              message ("Function clause uses %s which is a parameter and has special "
2238                       "meaning in a function clause.  (Special meaning assumed.)", s), 
2239              g_currentloc);
2240         }
2241     }
2242   else
2243     {
2244       if (uentry_isValid (ue))
2245         {
2246           ret = uentry_getSref (ue);
2247
2248           if (sRef_isFileOrGlobalScope (ret))
2249             {
2250               voptgenerror 
2251                 (FLG_SYNTAX, 
2252                  message ("Global variable %s used in function clause.  (Global variables "
2253                           "are not recognized in function clauses.  If there is "
2254                           "sufficient interest in support for this, it may be "
2255                           "added to a future release.  Send mail to "
2256                           "lclint@cs.virginia.edu.)",
2257                           s), 
2258                  g_currentloc);
2259               
2260               ret = sRef_undefined;
2261             }
2262         }
2263       else
2264         {
2265           fileloc loc = fileloc_decColumn (g_currentloc, cstring_length (s));
2266           ret = sRef_undefined; 
2267           
2268           voptgenerror 
2269             (FLG_UNRECOG, 
2270              message ("Unrecognized identifier in function clause: %s", s), 
2271              loc);
2272
2273           fileloc_free (loc);
2274         }
2275     }
2276   
2277   return ret;
2278 }
2279
2280 sRef modListArrayFetch (/*@exposed@*/ sRef s, /*@unused@*/ sRef mexp)
2281 {
2282   ctype ct = sRef_getType (s);
2283   ctype rt = ctype_realType (ct);
2284
2285   if (ctype_isAP (rt))
2286     {
2287       if (context_inHeader () && ctype_isAbstract (ct))
2288         {
2289           voptgenerror 
2290             (FLG_ABSTRACT,
2291              message
2292              ("Modifies clause in header file indexes abstract "
2293               "type %s (interface modifies clause should not depend "
2294               "on or expose type representation): %q",
2295               ctype_unparse (ct),
2296               sRef_unparse (s)),
2297              g_currentloc);
2298         }
2299       
2300       return (sRef_makeAnyArrayFetch (s));
2301     }
2302   else
2303     {
2304       voptgenerror
2305         (FLG_TYPE,
2306          message
2307          ("Implementation modifies clause uses array fetch on non-array (type %s): %q",
2308           ctype_unparse (ct), sRef_unparse (s)),
2309          g_currentloc);
2310       return s;
2311     }
2312 }
2313
2314 static void clabstract_prepareFunction (uentry e)
2315 {
2316   uentry_checkParams (e);
2317   DPRINTF (("After prepare: %s", uentry_unparseFull (e)));
2318 }
2319
2320 sRef clabstract_checkGlobal (exprNode e)
2321 {
2322   sRef s;
2323   llassert (exprNode_isInitializer (e));
2324
2325   s = exprNode_getSref (e);
2326   DPRINTF (("Initializer: %s -> %s", exprNode_unparse (e), sRef_unparse (s)));
2327
2328   exprNode_free (e);
2329   return sRef_copy (s);
2330 }
2331
2332
2333
2334
2335
2336
2337
2338
This page took 0.211331 seconds and 3 git commands to generate.