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