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