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