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