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