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